From 6882a04fb36642862b11efe514251d32070c3d65 Mon Sep 17 00:00:00 2001 From: Konstantin Tokarev Date: Thu, 25 Aug 2016 19:20:41 +0300 Subject: Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443) Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev --- Source/JavaScriptCore/runtime/ArgList.cpp | 15 +- Source/JavaScriptCore/runtime/ArgList.h | 32 +- Source/JavaScriptCore/runtime/Arguments.cpp | 438 ----- Source/JavaScriptCore/runtime/Arguments.h | 280 ---- Source/JavaScriptCore/runtime/ArgumentsMode.h | 39 + Source/JavaScriptCore/runtime/ArityCheckMode.h | 39 + Source/JavaScriptCore/runtime/ArrayBuffer.cpp | 66 + Source/JavaScriptCore/runtime/ArrayBuffer.h | 289 ++++ .../runtime/ArrayBufferNeuteringWatchpoint.cpp | 69 + .../runtime/ArrayBufferNeuteringWatchpoint.h | 60 + Source/JavaScriptCore/runtime/ArrayBufferView.cpp | 65 + Source/JavaScriptCore/runtime/ArrayBufferView.h | 211 +++ Source/JavaScriptCore/runtime/ArrayConstructor.cpp | 51 +- Source/JavaScriptCore/runtime/ArrayConstructor.h | 23 +- Source/JavaScriptCore/runtime/ArrayConventions.h | 9 +- .../runtime/ArrayIteratorPrototype.cpp | 70 + .../runtime/ArrayIteratorPrototype.h | 64 + Source/JavaScriptCore/runtime/ArrayPrototype.cpp | 1484 ++++++++--------- Source/JavaScriptCore/runtime/ArrayPrototype.h | 35 +- Source/JavaScriptCore/runtime/ArrayStorage.h | 9 +- .../JavaScriptCore/runtime/BasicBlockLocation.cpp | 100 ++ Source/JavaScriptCore/runtime/BasicBlockLocation.h | 74 + .../runtime/BatchedTransitionOptimizer.h | 6 +- .../JavaScriptCore/runtime/BooleanConstructor.cpp | 34 +- Source/JavaScriptCore/runtime/BooleanConstructor.h | 18 +- Source/JavaScriptCore/runtime/BooleanObject.cpp | 8 +- Source/JavaScriptCore/runtime/BooleanObject.h | 6 +- Source/JavaScriptCore/runtime/BooleanPrototype.cpp | 35 +- Source/JavaScriptCore/runtime/BooleanPrototype.h | 20 +- Source/JavaScriptCore/runtime/BundlePath.h | 39 + Source/JavaScriptCore/runtime/Butterfly.h | 31 +- Source/JavaScriptCore/runtime/ButterflyInlines.h | 98 +- .../runtime/CachedTranscendentalFunction.h | 101 -- Source/JavaScriptCore/runtime/CallData.cpp | 28 +- Source/JavaScriptCore/runtime/CallData.h | 14 +- Source/JavaScriptCore/runtime/ClassInfo.h | 76 +- Source/JavaScriptCore/runtime/ClonedArguments.cpp | 248 +++ Source/JavaScriptCore/runtime/ClonedArguments.h | 79 + Source/JavaScriptCore/runtime/CodeCache.cpp | 173 +- Source/JavaScriptCore/runtime/CodeCache.h | 142 +- .../JavaScriptCore/runtime/CommonIdentifiers.cpp | 55 +- Source/JavaScriptCore/runtime/CommonIdentifiers.h | 283 +++- Source/JavaScriptCore/runtime/CommonSlowPaths.cpp | 800 ++++++++++ Source/JavaScriptCore/runtime/CommonSlowPaths.h | 220 ++- .../runtime/CommonSlowPathsExceptions.cpp | 47 + .../runtime/CommonSlowPathsExceptions.h | 42 + .../JavaScriptCore/runtime/CompilationResult.cpp | 53 + Source/JavaScriptCore/runtime/CompilationResult.h | 71 + Source/JavaScriptCore/runtime/Completion.cpp | 164 +- Source/JavaScriptCore/runtime/Completion.h | 49 +- Source/JavaScriptCore/runtime/ConcurrentJITLock.h | 123 ++ Source/JavaScriptCore/runtime/ConsoleClient.cpp | 254 +++ Source/JavaScriptCore/runtime/ConsoleClient.h | 73 + Source/JavaScriptCore/runtime/ConsolePrototype.cpp | 400 +++++ Source/JavaScriptCore/runtime/ConsolePrototype.h | 61 + Source/JavaScriptCore/runtime/ConsoleTypes.h | 75 + Source/JavaScriptCore/runtime/ConstantMode.cpp | 46 + Source/JavaScriptCore/runtime/ConstantMode.h | 49 + Source/JavaScriptCore/runtime/ConstructAbility.h | 38 + Source/JavaScriptCore/runtime/ConstructData.cpp | 24 +- Source/JavaScriptCore/runtime/ConstructData.h | 62 +- .../JavaScriptCore/runtime/ControlFlowProfiler.cpp | 137 ++ .../JavaScriptCore/runtime/ControlFlowProfiler.h | 115 ++ .../JavaScriptCore/runtime/CustomGetterSetter.cpp | 50 + Source/JavaScriptCore/runtime/CustomGetterSetter.h | 77 + Source/JavaScriptCore/runtime/DataView.cpp | 60 + Source/JavaScriptCore/runtime/DataView.h | 102 ++ Source/JavaScriptCore/runtime/DateConstructor.cpp | 194 +-- Source/JavaScriptCore/runtime/DateConstructor.h | 55 +- Source/JavaScriptCore/runtime/DateConversion.h | 2 +- Source/JavaScriptCore/runtime/DateInstance.cpp | 22 +- Source/JavaScriptCore/runtime/DateInstance.h | 120 +- Source/JavaScriptCore/runtime/DateInstanceCache.h | 98 +- Source/JavaScriptCore/runtime/DatePrototype.cpp | 394 +++-- Source/JavaScriptCore/runtime/DatePrototype.h | 46 +- Source/JavaScriptCore/runtime/DirectArguments.cpp | 185 +++ Source/JavaScriptCore/runtime/DirectArguments.h | 158 ++ .../runtime/DirectArgumentsOffset.cpp | 42 + .../JavaScriptCore/runtime/DirectArgumentsOffset.h | 53 + Source/JavaScriptCore/runtime/DumpContext.cpp | 49 + Source/JavaScriptCore/runtime/DumpContext.h | 51 + Source/JavaScriptCore/runtime/EnumerationMode.h | 80 + Source/JavaScriptCore/runtime/Error.cpp | 219 ++- Source/JavaScriptCore/runtime/Error.h | 206 +-- Source/JavaScriptCore/runtime/ErrorConstructor.cpp | 35 +- Source/JavaScriptCore/runtime/ErrorConstructor.h | 45 +- .../JavaScriptCore/runtime/ErrorHandlingScope.cpp | 55 + Source/JavaScriptCore/runtime/ErrorHandlingScope.h | 45 + Source/JavaScriptCore/runtime/ErrorInstance.cpp | 124 +- Source/JavaScriptCore/runtime/ErrorInstance.h | 91 +- Source/JavaScriptCore/runtime/ErrorPrototype.cpp | 29 +- Source/JavaScriptCore/runtime/ErrorPrototype.h | 58 +- Source/JavaScriptCore/runtime/Exception.cpp | 83 + Source/JavaScriptCore/runtime/Exception.h | 80 + Source/JavaScriptCore/runtime/ExceptionFuzz.cpp | 57 + Source/JavaScriptCore/runtime/ExceptionFuzz.h | 49 + Source/JavaScriptCore/runtime/ExceptionHelpers.cpp | 247 ++- Source/JavaScriptCore/runtime/ExceptionHelpers.h | 48 +- Source/JavaScriptCore/runtime/Executable.cpp | 1013 +++++++----- Source/JavaScriptCore/runtime/Executable.h | 1287 +++++++-------- Source/JavaScriptCore/runtime/ExecutionHarness.h | 76 - Source/JavaScriptCore/runtime/Float32Array.h | 34 + Source/JavaScriptCore/runtime/Float64Array.h | 34 + .../JavaScriptCore/runtime/FunctionConstructor.cpp | 73 +- .../JavaScriptCore/runtime/FunctionConstructor.h | 56 +- .../runtime/FunctionExecutableDump.cpp | 18 +- .../runtime/FunctionHasExecutedCache.cpp | 100 ++ .../runtime/FunctionHasExecutedCache.h | 65 + .../JavaScriptCore/runtime/FunctionPrototype.cpp | 167 +- Source/JavaScriptCore/runtime/FunctionPrototype.h | 54 +- Source/JavaScriptCore/runtime/FunctionRareData.cpp | 93 ++ Source/JavaScriptCore/runtime/FunctionRareData.h | 121 ++ .../JavaScriptCore/runtime/GCActivityCallback.cpp | 204 --- Source/JavaScriptCore/runtime/GCActivityCallback.h | 110 -- .../runtime/GCActivityCallbackBlackBerry.cpp | 58 - Source/JavaScriptCore/runtime/GeneratorFrame.cpp | 97 ++ Source/JavaScriptCore/runtime/GeneratorFrame.h | 90 ++ .../runtime/GeneratorFunctionConstructor.cpp | 77 + .../runtime/GeneratorFunctionConstructor.h | 66 + .../runtime/GeneratorFunctionPrototype.cpp | 56 + .../runtime/GeneratorFunctionPrototype.h | 60 + .../JavaScriptCore/runtime/GeneratorPrototype.cpp | 62 + Source/JavaScriptCore/runtime/GeneratorPrototype.h | 64 + Source/JavaScriptCore/runtime/GenericArguments.h | 62 + .../runtime/GenericArgumentsInlines.h | 233 +++ Source/JavaScriptCore/runtime/GenericOffset.h | 113 ++ .../JavaScriptCore/runtime/GenericTypedArrayView.h | 118 ++ .../runtime/GenericTypedArrayViewInlines.h | 112 ++ Source/JavaScriptCore/runtime/GetPutInfo.h | 223 +++ Source/JavaScriptCore/runtime/GetterSetter.cpp | 73 +- Source/JavaScriptCore/runtime/GetterSetter.h | 160 +- Source/JavaScriptCore/runtime/Identifier.cpp | 124 +- Source/JavaScriptCore/runtime/Identifier.h | 481 +++--- Source/JavaScriptCore/runtime/IdentifierInlines.h | 154 ++ Source/JavaScriptCore/runtime/IndexingHeader.h | 21 +- .../JavaScriptCore/runtime/IndexingHeaderInlines.h | 2 +- Source/JavaScriptCore/runtime/IndexingType.cpp | 5 +- Source/JavaScriptCore/runtime/IndexingType.h | 51 +- Source/JavaScriptCore/runtime/InferredType.cpp | 600 +++++++ Source/JavaScriptCore/runtime/InferredType.h | 293 ++++ .../JavaScriptCore/runtime/InferredTypeTable.cpp | 166 ++ Source/JavaScriptCore/runtime/InferredTypeTable.h | 114 ++ Source/JavaScriptCore/runtime/InferredValue.cpp | 132 ++ Source/JavaScriptCore/runtime/InferredValue.h | 138 ++ .../JavaScriptCore/runtime/InitializeThreading.cpp | 52 +- .../JavaScriptCore/runtime/InitializeThreading.h | 8 +- .../runtime/InspectorInstrumentationObject.cpp | 99 ++ .../runtime/InspectorInstrumentationObject.h | 67 + Source/JavaScriptCore/runtime/Int16Array.h | 34 + Source/JavaScriptCore/runtime/Int32Array.h | 34 + Source/JavaScriptCore/runtime/Int8Array.h | 34 + .../runtime/IntegralTypedArrayBase.h | 63 + Source/JavaScriptCore/runtime/InternalFunction.cpp | 51 +- Source/JavaScriptCore/runtime/InternalFunction.h | 51 +- Source/JavaScriptCore/runtime/IntlCollator.cpp | 450 ++++++ Source/JavaScriptCore/runtime/IntlCollator.h | 86 + .../runtime/IntlCollatorConstructor.cpp | 178 +++ .../runtime/IntlCollatorConstructor.h | 67 + .../runtime/IntlCollatorPrototype.cpp | 152 ++ .../JavaScriptCore/runtime/IntlCollatorPrototype.h | 58 + .../JavaScriptCore/runtime/IntlDateTimeFormat.cpp | 917 +++++++++++ Source/JavaScriptCore/runtime/IntlDateTimeFormat.h | 108 ++ .../runtime/IntlDateTimeFormatConstructor.cpp | 179 +++ .../runtime/IntlDateTimeFormatConstructor.h | 67 + .../runtime/IntlDateTimeFormatPrototype.cpp | 157 ++ .../runtime/IntlDateTimeFormatPrototype.h | 58 + Source/JavaScriptCore/runtime/IntlNumberFormat.cpp | 454 ++++++ Source/JavaScriptCore/runtime/IntlNumberFormat.h | 87 + .../runtime/IntlNumberFormatConstructor.cpp | 179 +++ .../runtime/IntlNumberFormatConstructor.h | 67 + .../runtime/IntlNumberFormatPrototype.cpp | 127 ++ .../runtime/IntlNumberFormatPrototype.h | 58 + Source/JavaScriptCore/runtime/IntlObject.cpp | 998 ++++++++++++ Source/JavaScriptCore/runtime/IntlObject.h | 76 + Source/JavaScriptCore/runtime/Intrinsic.h | 25 +- Source/JavaScriptCore/runtime/IterationStatus.h | 38 + .../JavaScriptCore/runtime/IteratorOperations.cpp | 156 ++ Source/JavaScriptCore/runtime/IteratorOperations.h | 46 + .../JavaScriptCore/runtime/IteratorPrototype.cpp | 50 + Source/JavaScriptCore/runtime/IteratorPrototype.h | 62 + .../JavaScriptCore/runtime/JSAPIValueWrapper.cpp | 4 +- Source/JavaScriptCore/runtime/JSAPIValueWrapper.h | 70 +- Source/JavaScriptCore/runtime/JSActivation.cpp | 264 --- Source/JavaScriptCore/runtime/JSActivation.h | 214 --- Source/JavaScriptCore/runtime/JSArray.cpp | 1108 ++++--------- Source/JavaScriptCore/runtime/JSArray.h | 145 +- Source/JavaScriptCore/runtime/JSArrayBuffer.cpp | 129 ++ Source/JavaScriptCore/runtime/JSArrayBuffer.h | 75 + .../runtime/JSArrayBufferConstructor.cpp | 133 ++ .../runtime/JSArrayBufferConstructor.h | 59 + .../runtime/JSArrayBufferPrototype.cpp | 106 ++ .../runtime/JSArrayBufferPrototype.h | 52 + .../JavaScriptCore/runtime/JSArrayBufferView.cpp | 234 +++ Source/JavaScriptCore/runtime/JSArrayBufferView.h | 203 +++ .../runtime/JSArrayBufferViewInlines.h | 83 + Source/JavaScriptCore/runtime/JSArrayIterator.cpp | 70 + Source/JavaScriptCore/runtime/JSArrayIterator.h | 74 + Source/JavaScriptCore/runtime/JSBoundFunction.cpp | 63 +- Source/JavaScriptCore/runtime/JSBoundFunction.h | 19 +- .../runtime/JSBoundSlotBaseFunction.cpp | 94 ++ .../runtime/JSBoundSlotBaseFunction.h | 75 + Source/JavaScriptCore/runtime/JSCInlines.h | 56 + Source/JavaScriptCore/runtime/JSCJSValue.cpp | 204 ++- Source/JavaScriptCore/runtime/JSCJSValue.h | 164 +- Source/JavaScriptCore/runtime/JSCJSValueInlines.h | 250 ++- Source/JavaScriptCore/runtime/JSCallee.cpp | 69 + Source/JavaScriptCore/runtime/JSCallee.h | 108 ++ Source/JavaScriptCore/runtime/JSCell.cpp | 119 +- Source/JavaScriptCore/runtime/JSCell.h | 146 +- Source/JavaScriptCore/runtime/JSCellInlines.h | 172 +- Source/JavaScriptCore/runtime/JSChunk.cpp | 28 - Source/JavaScriptCore/runtime/JSChunk.h | 31 - Source/JavaScriptCore/runtime/JSConsole.cpp | 36 + Source/JavaScriptCore/runtime/JSConsole.h | 65 + Source/JavaScriptCore/runtime/JSDataView.cpp | 185 +++ Source/JavaScriptCore/runtime/JSDataView.h | 83 + .../JavaScriptCore/runtime/JSDataViewPrototype.cpp | 305 ++++ .../JavaScriptCore/runtime/JSDataViewPrototype.h | 57 + Source/JavaScriptCore/runtime/JSDateMath.cpp | 60 +- Source/JavaScriptCore/runtime/JSDateMath.h | 12 +- .../JavaScriptCore/runtime/JSDestructibleObject.h | 11 - .../JavaScriptCore/runtime/JSEnvironmentRecord.cpp | 46 + .../JavaScriptCore/runtime/JSEnvironmentRecord.h | 118 ++ Source/JavaScriptCore/runtime/JSExportMacros.h | 7 +- Source/JavaScriptCore/runtime/JSFloat32Array.h | 32 + Source/JavaScriptCore/runtime/JSFloat64Array.h | 32 + Source/JavaScriptCore/runtime/JSFunction.cpp | 444 ++++-- Source/JavaScriptCore/runtime/JSFunction.h | 322 ++-- Source/JavaScriptCore/runtime/JSFunctionInlines.h | 61 +- .../JavaScriptCore/runtime/JSGeneratorFunction.cpp | 67 + .../JavaScriptCore/runtime/JSGeneratorFunction.h | 82 + .../runtime/JSGenericTypedArrayView.h | 369 +++++ .../runtime/JSGenericTypedArrayViewConstructor.h | 58 + .../JSGenericTypedArrayViewConstructorInlines.h | 273 ++++ .../runtime/JSGenericTypedArrayViewInlines.h | 546 +++++++ .../runtime/JSGenericTypedArrayViewPrototype.h | 54 + .../JSGenericTypedArrayViewPrototypeFunctions.h | 432 +++++ .../JSGenericTypedArrayViewPrototypeInlines.h | 73 + .../runtime/JSGlobalLexicalEnvironment.cpp | 50 + .../runtime/JSGlobalLexicalEnvironment.h | 71 + Source/JavaScriptCore/runtime/JSGlobalObject.cpp | 1035 ++++++++---- Source/JavaScriptCore/runtime/JSGlobalObject.h | 491 ++++-- .../runtime/JSGlobalObjectDebuggable.cpp | 88 + .../runtime/JSGlobalObjectDebuggable.h | 74 + .../runtime/JSGlobalObjectFunctions.cpp | 332 +++- .../runtime/JSGlobalObjectFunctions.h | 12 +- Source/JavaScriptCore/runtime/JSInt16Array.h | 32 + Source/JavaScriptCore/runtime/JSInt32Array.h | 32 + Source/JavaScriptCore/runtime/JSInt8Array.h | 32 + .../JavaScriptCore/runtime/JSInternalPromise.cpp | 69 + Source/JavaScriptCore/runtime/JSInternalPromise.h | 60 + .../runtime/JSInternalPromiseConstructor.cpp | 93 ++ .../runtime/JSInternalPromiseConstructor.h | 55 + .../runtime/JSInternalPromiseDeferred.cpp | 81 + .../runtime/JSInternalPromiseDeferred.h | 59 + .../runtime/JSInternalPromisePrototype.cpp | 61 + .../runtime/JSInternalPromisePrototype.h | 49 + Source/JavaScriptCore/runtime/JSJob.cpp | 76 + Source/JavaScriptCore/runtime/JSJob.h | 41 + .../runtime/JSLexicalEnvironment.cpp | 115 ++ .../JavaScriptCore/runtime/JSLexicalEnvironment.h | 94 ++ Source/JavaScriptCore/runtime/JSLock.cpp | 259 +-- Source/JavaScriptCore/runtime/JSLock.h | 189 ++- Source/JavaScriptCore/runtime/JSMap.cpp | 98 ++ Source/JavaScriptCore/runtime/JSMap.h | 134 ++ Source/JavaScriptCore/runtime/JSMapIterator.cpp | 70 + Source/JavaScriptCore/runtime/JSMapIterator.h | 118 ++ .../JavaScriptCore/runtime/JSModuleEnvironment.cpp | 133 ++ .../JavaScriptCore/runtime/JSModuleEnvironment.h | 103 ++ .../runtime/JSModuleNamespaceObject.cpp | 197 +++ .../runtime/JSModuleNamespaceObject.h | 80 + Source/JavaScriptCore/runtime/JSModuleRecord.cpp | 903 +++++++++++ Source/JavaScriptCore/runtime/JSModuleRecord.h | 221 +++ Source/JavaScriptCore/runtime/JSNameScope.cpp | 81 - Source/JavaScriptCore/runtime/JSNameScope.h | 94 -- .../JavaScriptCore/runtime/JSNativeStdFunction.cpp | 76 + .../JavaScriptCore/runtime/JSNativeStdFunction.h | 69 + Source/JavaScriptCore/runtime/JSNotAnObject.cpp | 18 +- Source/JavaScriptCore/runtime/JSNotAnObject.h | 75 +- Source/JavaScriptCore/runtime/JSONObject.cpp | 242 ++- Source/JavaScriptCore/runtime/JSONObject.h | 50 +- Source/JavaScriptCore/runtime/JSObject.cpp | 1687 ++++++++++++-------- Source/JavaScriptCore/runtime/JSObject.h | 973 +++++------ Source/JavaScriptCore/runtime/JSObjectInlines.h | 69 + Source/JavaScriptCore/runtime/JSPromise.cpp | 91 ++ Source/JavaScriptCore/runtime/JSPromise.h | 62 + .../runtime/JSPromiseConstructor.cpp | 139 ++ .../JavaScriptCore/runtime/JSPromiseConstructor.h | 62 + .../JavaScriptCore/runtime/JSPromiseDeferred.cpp | 129 ++ Source/JavaScriptCore/runtime/JSPromiseDeferred.h | 75 + .../JavaScriptCore/runtime/JSPromisePrototype.cpp | 93 ++ Source/JavaScriptCore/runtime/JSPromisePrototype.h | 55 + .../runtime/JSPropertyNameEnumerator.cpp | 94 ++ .../runtime/JSPropertyNameEnumerator.h | 146 ++ .../runtime/JSPropertyNameIterator.cpp | 195 ++- .../runtime/JSPropertyNameIterator.h | 148 +- Source/JavaScriptCore/runtime/JSProxy.cpp | 69 +- Source/JavaScriptCore/runtime/JSProxy.h | 21 +- Source/JavaScriptCore/runtime/JSScope.cpp | 746 +++------ Source/JavaScriptCore/runtime/JSScope.h | 59 +- .../runtime/JSSegmentedVariableObject.cpp | 40 +- .../runtime/JSSegmentedVariableObject.h | 42 +- Source/JavaScriptCore/runtime/JSSet.cpp | 90 ++ Source/JavaScriptCore/runtime/JSSet.h | 129 ++ Source/JavaScriptCore/runtime/JSSetIterator.cpp | 70 + Source/JavaScriptCore/runtime/JSSetIterator.h | 105 ++ .../JavaScriptCore/runtime/JSStaticScopeObject.cpp | 0 .../JavaScriptCore/runtime/JSStaticScopeObject.h | 0 Source/JavaScriptCore/runtime/JSString.cpp | 378 +++-- Source/JavaScriptCore/runtime/JSString.h | 441 +++-- Source/JavaScriptCore/runtime/JSStringBuilder.h | 139 +- Source/JavaScriptCore/runtime/JSStringIterator.cpp | 61 + Source/JavaScriptCore/runtime/JSStringIterator.h | 66 + Source/JavaScriptCore/runtime/JSStringJoiner.cpp | 145 +- Source/JavaScriptCore/runtime/JSStringJoiner.h | 122 +- .../JavaScriptCore/runtime/JSSymbolTableObject.cpp | 35 +- .../JavaScriptCore/runtime/JSSymbolTableObject.h | 192 ++- .../runtime/JSTemplateRegistryKey.cpp | 57 + .../JavaScriptCore/runtime/JSTemplateRegistryKey.h | 61 + Source/JavaScriptCore/runtime/JSType.h | 45 +- Source/JavaScriptCore/runtime/JSTypeInfo.h | 157 +- .../runtime/JSTypedArrayConstructors.cpp | 50 + .../runtime/JSTypedArrayConstructors.h | 48 + .../runtime/JSTypedArrayPrototypes.cpp | 51 + .../runtime/JSTypedArrayPrototypes.h | 47 + .../runtime/JSTypedArrayViewConstructor.cpp | 118 ++ .../runtime/JSTypedArrayViewConstructor.h | 64 + .../runtime/JSTypedArrayViewPrototype.cpp | 301 ++++ .../runtime/JSTypedArrayViewPrototype.h | 55 + Source/JavaScriptCore/runtime/JSTypedArrays.cpp | 55 + Source/JavaScriptCore/runtime/JSTypedArrays.h | 48 + Source/JavaScriptCore/runtime/JSUint16Array.h | 32 + Source/JavaScriptCore/runtime/JSUint32Array.h | 32 + Source/JavaScriptCore/runtime/JSUint8Array.h | 32 + .../JavaScriptCore/runtime/JSUint8ClampedArray.h | 32 + Source/JavaScriptCore/runtime/JSVariableObject.cpp | 38 - Source/JavaScriptCore/runtime/JSVariableObject.h | 77 - Source/JavaScriptCore/runtime/JSWeakMap.cpp | 52 + Source/JavaScriptCore/runtime/JSWeakMap.h | 81 + Source/JavaScriptCore/runtime/JSWeakSet.cpp | 52 + Source/JavaScriptCore/runtime/JSWeakSet.h | 81 + Source/JavaScriptCore/runtime/JSWithScope.cpp | 9 +- Source/JavaScriptCore/runtime/JSWithScope.h | 24 +- Source/JavaScriptCore/runtime/JSWrapperObject.cpp | 9 +- Source/JavaScriptCore/runtime/JSWrapperObject.h | 93 +- Source/JavaScriptCore/runtime/LiteralParser.cpp | 59 +- Source/JavaScriptCore/runtime/LiteralParser.h | 9 +- Source/JavaScriptCore/runtime/Lookup.cpp | 83 +- Source/JavaScriptCore/runtime/Lookup.h | 579 ++++--- Source/JavaScriptCore/runtime/MapConstructor.cpp | 146 ++ Source/JavaScriptCore/runtime/MapConstructor.h | 66 + Source/JavaScriptCore/runtime/MapData.h | 219 +++ Source/JavaScriptCore/runtime/MapDataInlines.h | 290 ++++ .../runtime/MapIteratorPrototype.cpp | 65 + .../JavaScriptCore/runtime/MapIteratorPrototype.h | 61 + Source/JavaScriptCore/runtime/MapPrototype.cpp | 215 +++ Source/JavaScriptCore/runtime/MapPrototype.h | 68 + Source/JavaScriptCore/runtime/MathCommon.cpp | 443 +++++ Source/JavaScriptCore/runtime/MathCommon.h | 63 + Source/JavaScriptCore/runtime/MathObject.cpp | 678 +++----- Source/JavaScriptCore/runtime/MathObject.h | 55 +- Source/JavaScriptCore/runtime/MemoryStatistics.cpp | 5 +- Source/JavaScriptCore/runtime/MemoryStatistics.h | 2 +- Source/JavaScriptCore/runtime/Microtask.h | 46 + .../JavaScriptCore/runtime/ModuleLoaderObject.cpp | 394 +++++ Source/JavaScriptCore/runtime/ModuleLoaderObject.h | 88 + Source/JavaScriptCore/runtime/NameConstructor.cpp | 69 - Source/JavaScriptCore/runtime/NameConstructor.h | 65 - Source/JavaScriptCore/runtime/NameInstance.cpp | 47 - Source/JavaScriptCore/runtime/NameInstance.h | 77 - Source/JavaScriptCore/runtime/NamePrototype.cpp | 86 - Source/JavaScriptCore/runtime/NamePrototype.h | 64 - .../runtime/NativeErrorConstructor.cpp | 51 +- .../runtime/NativeErrorConstructor.h | 67 +- .../runtime/NativeErrorPrototype.cpp | 16 +- .../JavaScriptCore/runtime/NativeErrorPrototype.h | 39 +- .../runtime/NativeStdFunctionCell.cpp | 58 + .../JavaScriptCore/runtime/NativeStdFunctionCell.h | 61 + .../JavaScriptCore/runtime/NullGetterFunction.cpp | 52 + Source/JavaScriptCore/runtime/NullGetterFunction.h | 62 + .../JavaScriptCore/runtime/NullSetterFunction.cpp | 91 ++ Source/JavaScriptCore/runtime/NullSetterFunction.h | 62 + .../JavaScriptCore/runtime/NumberConstructor.cpp | 152 +- Source/JavaScriptCore/runtime/NumberConstructor.h | 67 +- Source/JavaScriptCore/runtime/NumberObject.cpp | 8 +- Source/JavaScriptCore/runtime/NumberObject.h | 48 +- Source/JavaScriptCore/runtime/NumberPrototype.cpp | 54 +- Source/JavaScriptCore/runtime/NumberPrototype.h | 53 +- Source/JavaScriptCore/runtime/NumericStrings.h | 106 +- .../JavaScriptCore/runtime/ObjectConstructor.cpp | 420 +++-- Source/JavaScriptCore/runtime/ObjectConstructor.h | 106 +- Source/JavaScriptCore/runtime/ObjectPrototype.cpp | 167 +- Source/JavaScriptCore/runtime/ObjectPrototype.h | 30 +- Source/JavaScriptCore/runtime/Operations.cpp | 28 +- Source/JavaScriptCore/runtime/Operations.h | 97 +- Source/JavaScriptCore/runtime/Options.cpp | 656 ++++++-- Source/JavaScriptCore/runtime/Options.h | 522 ++++-- Source/JavaScriptCore/runtime/PrivateName.h | 22 +- .../JavaScriptCore/runtime/PropertyDescriptor.cpp | 36 +- Source/JavaScriptCore/runtime/PropertyDescriptor.h | 114 +- .../JavaScriptCore/runtime/PropertyMapHashTable.h | 154 +- Source/JavaScriptCore/runtime/PropertyName.h | 99 +- .../JavaScriptCore/runtime/PropertyNameArray.cpp | 55 - Source/JavaScriptCore/runtime/PropertyNameArray.h | 202 ++- Source/JavaScriptCore/runtime/PropertyOffset.h | 1 - Source/JavaScriptCore/runtime/PropertySlot.cpp | 19 +- Source/JavaScriptCore/runtime/PropertySlot.h | 468 +++--- Source/JavaScriptCore/runtime/PropertyTable.cpp | 45 +- Source/JavaScriptCore/runtime/Protect.h | 58 +- Source/JavaScriptCore/runtime/PrototypeMap.cpp | 38 +- Source/JavaScriptCore/runtime/PrototypeMap.h | 16 +- Source/JavaScriptCore/runtime/ProxyConstructor.cpp | 89 ++ Source/JavaScriptCore/runtime/ProxyConstructor.h | 59 + Source/JavaScriptCore/runtime/ProxyObject.cpp | 311 ++++ Source/JavaScriptCore/runtime/ProxyObject.h | 76 + Source/JavaScriptCore/runtime/PureNaN.h | 98 ++ Source/JavaScriptCore/runtime/PutPropertySlot.h | 148 +- Source/JavaScriptCore/runtime/ReflectObject.cpp | 217 +++ Source/JavaScriptCore/runtime/ReflectObject.h | 63 + Source/JavaScriptCore/runtime/RegExp.cpp | 100 +- Source/JavaScriptCore/runtime/RegExp.h | 125 +- Source/JavaScriptCore/runtime/RegExpCache.cpp | 9 +- Source/JavaScriptCore/runtime/RegExpCache.h | 14 +- .../JavaScriptCore/runtime/RegExpCachedResult.cpp | 34 +- Source/JavaScriptCore/runtime/RegExpCachedResult.h | 91 +- .../JavaScriptCore/runtime/RegExpConstructor.cpp | 189 +-- Source/JavaScriptCore/runtime/RegExpConstructor.h | 150 +- .../JavaScriptCore/runtime/RegExpMatchesArray.cpp | 108 +- Source/JavaScriptCore/runtime/RegExpMatchesArray.h | 117 +- Source/JavaScriptCore/runtime/RegExpObject.cpp | 213 +-- Source/JavaScriptCore/runtime/RegExpObject.h | 131 +- Source/JavaScriptCore/runtime/RegExpPrototype.cpp | 295 +++- Source/JavaScriptCore/runtime/RegExpPrototype.h | 52 +- Source/JavaScriptCore/runtime/RuntimeFlags.h | 99 ++ Source/JavaScriptCore/runtime/RuntimeType.cpp | 88 + Source/JavaScriptCore/runtime/RuntimeType.h | 60 + Source/JavaScriptCore/runtime/SamplingCounter.cpp | 2 +- Source/JavaScriptCore/runtime/SamplingCounter.h | 2 +- Source/JavaScriptCore/runtime/SamplingProfiler.cpp | 786 +++++++++ Source/JavaScriptCore/runtime/SamplingProfiler.h | 176 ++ Source/JavaScriptCore/runtime/ScopeOffset.cpp | 42 + Source/JavaScriptCore/runtime/ScopeOffset.h | 51 + Source/JavaScriptCore/runtime/ScopedArguments.cpp | 154 ++ Source/JavaScriptCore/runtime/ScopedArguments.h | 157 ++ .../runtime/ScopedArgumentsTable.cpp | 109 ++ .../JavaScriptCore/runtime/ScopedArgumentsTable.h | 96 ++ Source/JavaScriptCore/runtime/SetConstructor.cpp | 128 ++ Source/JavaScriptCore/runtime/SetConstructor.h | 66 + .../runtime/SetIteratorPrototype.cpp | 64 + .../JavaScriptCore/runtime/SetIteratorPrototype.h | 61 + Source/JavaScriptCore/runtime/SetPrototype.cpp | 193 +++ Source/JavaScriptCore/runtime/SetPrototype.h | 68 + .../runtime/SimpleTypedArrayController.cpp | 51 + .../runtime/SimpleTypedArrayController.h | 56 + Source/JavaScriptCore/runtime/SlowPathReturnType.h | 86 + Source/JavaScriptCore/runtime/SmallStrings.cpp | 45 +- Source/JavaScriptCore/runtime/SmallStrings.h | 124 +- .../JavaScriptCore/runtime/SparseArrayValueMap.cpp | 63 +- .../JavaScriptCore/runtime/SparseArrayValueMap.h | 14 +- Source/JavaScriptCore/runtime/StackAlignment.h | 65 + .../runtime/StrictEvalActivation.cpp | 14 +- .../JavaScriptCore/runtime/StrictEvalActivation.h | 20 +- .../JavaScriptCore/runtime/StringConstructor.cpp | 79 +- Source/JavaScriptCore/runtime/StringConstructor.h | 53 +- .../runtime/StringIteratorPrototype.cpp | 66 + .../runtime/StringIteratorPrototype.h | 64 + Source/JavaScriptCore/runtime/StringObject.cpp | 57 +- Source/JavaScriptCore/runtime/StringObject.h | 103 +- Source/JavaScriptCore/runtime/StringPrototype.cpp | 1144 +++++++++---- Source/JavaScriptCore/runtime/StringPrototype.h | 49 +- .../runtime/StringRecursionChecker.cpp | 4 +- .../runtime/StringRecursionChecker.h | 24 +- Source/JavaScriptCore/runtime/Structure.cpp | 1007 ++++++++---- Source/JavaScriptCore/runtime/Structure.h | 540 +++++-- Source/JavaScriptCore/runtime/StructureChain.cpp | 11 +- Source/JavaScriptCore/runtime/StructureChain.h | 103 +- Source/JavaScriptCore/runtime/StructureIDBlob.h | 95 ++ Source/JavaScriptCore/runtime/StructureIDTable.cpp | 119 ++ Source/JavaScriptCore/runtime/StructureIDTable.h | 94 ++ Source/JavaScriptCore/runtime/StructureInlines.h | 200 ++- .../JavaScriptCore/runtime/StructureRareData.cpp | 180 ++- Source/JavaScriptCore/runtime/StructureRareData.h | 48 +- .../runtime/StructureRareDataInlines.h | 10 +- .../runtime/StructureTransitionTable.h | 49 +- Source/JavaScriptCore/runtime/Symbol.cpp | 96 ++ Source/JavaScriptCore/runtime/Symbol.h | 110 ++ .../JavaScriptCore/runtime/SymbolConstructor.cpp | 128 ++ Source/JavaScriptCore/runtime/SymbolConstructor.h | 69 + Source/JavaScriptCore/runtime/SymbolObject.cpp | 56 + Source/JavaScriptCore/runtime/SymbolObject.h | 67 + Source/JavaScriptCore/runtime/SymbolPrototype.cpp | 107 ++ Source/JavaScriptCore/runtime/SymbolPrototype.h | 66 + Source/JavaScriptCore/runtime/SymbolTable.cpp | 225 ++- Source/JavaScriptCore/runtime/SymbolTable.h | 493 ++++-- Source/JavaScriptCore/runtime/TemplateRegistry.cpp | 71 + Source/JavaScriptCore/runtime/TemplateRegistry.h | 48 + .../JavaScriptCore/runtime/TemplateRegistryKey.h | 103 ++ Source/JavaScriptCore/runtime/TestRunnerUtils.cpp | 142 ++ Source/JavaScriptCore/runtime/TestRunnerUtils.h | 57 + Source/JavaScriptCore/runtime/ToNativeFromValue.h | 54 + Source/JavaScriptCore/runtime/Tracing.d | 6 +- Source/JavaScriptCore/runtime/Tracing.h | 4 +- .../JavaScriptCore/runtime/TypeLocationCache.cpp | 61 + Source/JavaScriptCore/runtime/TypeLocationCache.h | 68 + Source/JavaScriptCore/runtime/TypeProfiler.cpp | 168 ++ Source/JavaScriptCore/runtime/TypeProfiler.h | 144 ++ Source/JavaScriptCore/runtime/TypeProfilerLog.cpp | 98 ++ Source/JavaScriptCore/runtime/TypeProfilerLog.h | 84 + Source/JavaScriptCore/runtime/TypeSet.cpp | 587 +++++++ Source/JavaScriptCore/runtime/TypeSet.h | 110 ++ Source/JavaScriptCore/runtime/TypedArrayAdaptors.h | 218 +++ Source/JavaScriptCore/runtime/TypedArrayBase.h | 153 ++ .../runtime/TypedArrayController.cpp | 35 + .../JavaScriptCore/runtime/TypedArrayController.h | 49 + .../JavaScriptCore/runtime/TypedArrayDescriptor.h | 76 - Source/JavaScriptCore/runtime/TypedArrayInlines.h | 37 + Source/JavaScriptCore/runtime/TypedArrayType.cpp | 146 ++ Source/JavaScriptCore/runtime/TypedArrayType.h | 162 ++ Source/JavaScriptCore/runtime/TypedArrays.h | 47 + Source/JavaScriptCore/runtime/TypeofType.cpp | 63 + Source/JavaScriptCore/runtime/TypeofType.h | 52 + Source/JavaScriptCore/runtime/Uint16Array.h | 34 + Source/JavaScriptCore/runtime/Uint32Array.h | 34 + Source/JavaScriptCore/runtime/Uint8Array.h | 34 + Source/JavaScriptCore/runtime/Uint8ClampedArray.h | 34 + Source/JavaScriptCore/runtime/VM.cpp | 703 +++++--- Source/JavaScriptCore/runtime/VM.h | 940 ++++++----- Source/JavaScriptCore/runtime/VMEntryScope.cpp | 81 + Source/JavaScriptCore/runtime/VMEntryScope.h | 56 + Source/JavaScriptCore/runtime/VMInlines.h | 44 + Source/JavaScriptCore/runtime/VMStackBounds.h | 71 - Source/JavaScriptCore/runtime/VarOffset.cpp | 76 + Source/JavaScriptCore/runtime/VarOffset.h | 247 +++ Source/JavaScriptCore/runtime/Watchdog.cpp | 223 ++- Source/JavaScriptCore/runtime/Watchdog.h | 89 +- Source/JavaScriptCore/runtime/WatchdogMac.cpp | 72 - Source/JavaScriptCore/runtime/WatchdogNone.cpp | 50 - Source/JavaScriptCore/runtime/WeakGCMap.h | 114 +- Source/JavaScriptCore/runtime/WeakGCMapInlines.h | 59 + .../JavaScriptCore/runtime/WeakMapConstructor.cpp | 144 ++ Source/JavaScriptCore/runtime/WeakMapConstructor.h | 66 + Source/JavaScriptCore/runtime/WeakMapData.cpp | 150 ++ Source/JavaScriptCore/runtime/WeakMapData.h | 95 ++ Source/JavaScriptCore/runtime/WeakMapPrototype.cpp | 112 ++ Source/JavaScriptCore/runtime/WeakMapPrototype.h | 61 + Source/JavaScriptCore/runtime/WeakRandom.h | 94 -- .../JavaScriptCore/runtime/WeakSetConstructor.cpp | 125 ++ Source/JavaScriptCore/runtime/WeakSetConstructor.h | 66 + Source/JavaScriptCore/runtime/WeakSetPrototype.cpp | 99 ++ Source/JavaScriptCore/runtime/WeakSetPrototype.h | 61 + Source/JavaScriptCore/runtime/WriteBarrier.h | 88 +- .../JavaScriptCore/runtime/WriteBarrierInlines.h | 67 + 552 files changed, 56831 insertions(+), 17451 deletions(-) delete mode 100644 Source/JavaScriptCore/runtime/Arguments.cpp delete mode 100644 Source/JavaScriptCore/runtime/Arguments.h create mode 100644 Source/JavaScriptCore/runtime/ArgumentsMode.h create mode 100644 Source/JavaScriptCore/runtime/ArityCheckMode.h create mode 100644 Source/JavaScriptCore/runtime/ArrayBuffer.cpp create mode 100644 Source/JavaScriptCore/runtime/ArrayBuffer.h create mode 100644 Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.cpp create mode 100644 Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.h create mode 100644 Source/JavaScriptCore/runtime/ArrayBufferView.cpp create mode 100644 Source/JavaScriptCore/runtime/ArrayBufferView.h create mode 100644 Source/JavaScriptCore/runtime/ArrayIteratorPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/ArrayIteratorPrototype.h create mode 100644 Source/JavaScriptCore/runtime/BasicBlockLocation.cpp create mode 100644 Source/JavaScriptCore/runtime/BasicBlockLocation.h create mode 100644 Source/JavaScriptCore/runtime/BundlePath.h delete mode 100644 Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h create mode 100644 Source/JavaScriptCore/runtime/ClonedArguments.cpp create mode 100644 Source/JavaScriptCore/runtime/ClonedArguments.h create mode 100644 Source/JavaScriptCore/runtime/CommonSlowPaths.cpp create mode 100644 Source/JavaScriptCore/runtime/CommonSlowPathsExceptions.cpp create mode 100644 Source/JavaScriptCore/runtime/CommonSlowPathsExceptions.h create mode 100644 Source/JavaScriptCore/runtime/CompilationResult.cpp create mode 100644 Source/JavaScriptCore/runtime/CompilationResult.h create mode 100644 Source/JavaScriptCore/runtime/ConcurrentJITLock.h create mode 100644 Source/JavaScriptCore/runtime/ConsoleClient.cpp create mode 100644 Source/JavaScriptCore/runtime/ConsoleClient.h create mode 100644 Source/JavaScriptCore/runtime/ConsolePrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/ConsolePrototype.h create mode 100644 Source/JavaScriptCore/runtime/ConsoleTypes.h create mode 100644 Source/JavaScriptCore/runtime/ConstantMode.cpp create mode 100644 Source/JavaScriptCore/runtime/ConstantMode.h create mode 100644 Source/JavaScriptCore/runtime/ConstructAbility.h create mode 100644 Source/JavaScriptCore/runtime/ControlFlowProfiler.cpp create mode 100644 Source/JavaScriptCore/runtime/ControlFlowProfiler.h create mode 100644 Source/JavaScriptCore/runtime/CustomGetterSetter.cpp create mode 100644 Source/JavaScriptCore/runtime/CustomGetterSetter.h create mode 100644 Source/JavaScriptCore/runtime/DataView.cpp create mode 100644 Source/JavaScriptCore/runtime/DataView.h create mode 100644 Source/JavaScriptCore/runtime/DirectArguments.cpp create mode 100644 Source/JavaScriptCore/runtime/DirectArguments.h create mode 100644 Source/JavaScriptCore/runtime/DirectArgumentsOffset.cpp create mode 100644 Source/JavaScriptCore/runtime/DirectArgumentsOffset.h create mode 100644 Source/JavaScriptCore/runtime/DumpContext.cpp create mode 100644 Source/JavaScriptCore/runtime/DumpContext.h create mode 100644 Source/JavaScriptCore/runtime/EnumerationMode.h create mode 100644 Source/JavaScriptCore/runtime/ErrorHandlingScope.cpp create mode 100644 Source/JavaScriptCore/runtime/ErrorHandlingScope.h create mode 100644 Source/JavaScriptCore/runtime/Exception.cpp create mode 100644 Source/JavaScriptCore/runtime/Exception.h create mode 100644 Source/JavaScriptCore/runtime/ExceptionFuzz.cpp create mode 100644 Source/JavaScriptCore/runtime/ExceptionFuzz.h delete mode 100644 Source/JavaScriptCore/runtime/ExecutionHarness.h create mode 100644 Source/JavaScriptCore/runtime/Float32Array.h create mode 100644 Source/JavaScriptCore/runtime/Float64Array.h create mode 100644 Source/JavaScriptCore/runtime/FunctionHasExecutedCache.cpp create mode 100644 Source/JavaScriptCore/runtime/FunctionHasExecutedCache.h create mode 100644 Source/JavaScriptCore/runtime/FunctionRareData.cpp create mode 100644 Source/JavaScriptCore/runtime/FunctionRareData.h delete mode 100644 Source/JavaScriptCore/runtime/GCActivityCallback.cpp delete mode 100644 Source/JavaScriptCore/runtime/GCActivityCallback.h delete mode 100644 Source/JavaScriptCore/runtime/GCActivityCallbackBlackBerry.cpp create mode 100644 Source/JavaScriptCore/runtime/GeneratorFrame.cpp create mode 100644 Source/JavaScriptCore/runtime/GeneratorFrame.h create mode 100644 Source/JavaScriptCore/runtime/GeneratorFunctionConstructor.cpp create mode 100644 Source/JavaScriptCore/runtime/GeneratorFunctionConstructor.h create mode 100644 Source/JavaScriptCore/runtime/GeneratorFunctionPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/GeneratorFunctionPrototype.h create mode 100644 Source/JavaScriptCore/runtime/GeneratorPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/GeneratorPrototype.h create mode 100644 Source/JavaScriptCore/runtime/GenericArguments.h create mode 100644 Source/JavaScriptCore/runtime/GenericArgumentsInlines.h create mode 100644 Source/JavaScriptCore/runtime/GenericOffset.h create mode 100644 Source/JavaScriptCore/runtime/GenericTypedArrayView.h create mode 100644 Source/JavaScriptCore/runtime/GenericTypedArrayViewInlines.h create mode 100644 Source/JavaScriptCore/runtime/GetPutInfo.h create mode 100644 Source/JavaScriptCore/runtime/IdentifierInlines.h create mode 100644 Source/JavaScriptCore/runtime/InferredType.cpp create mode 100644 Source/JavaScriptCore/runtime/InferredType.h create mode 100644 Source/JavaScriptCore/runtime/InferredTypeTable.cpp create mode 100644 Source/JavaScriptCore/runtime/InferredTypeTable.h create mode 100644 Source/JavaScriptCore/runtime/InferredValue.cpp create mode 100644 Source/JavaScriptCore/runtime/InferredValue.h create mode 100644 Source/JavaScriptCore/runtime/InspectorInstrumentationObject.cpp create mode 100644 Source/JavaScriptCore/runtime/InspectorInstrumentationObject.h create mode 100644 Source/JavaScriptCore/runtime/Int16Array.h create mode 100644 Source/JavaScriptCore/runtime/Int32Array.h create mode 100644 Source/JavaScriptCore/runtime/Int8Array.h create mode 100644 Source/JavaScriptCore/runtime/IntegralTypedArrayBase.h create mode 100644 Source/JavaScriptCore/runtime/IntlCollator.cpp create mode 100644 Source/JavaScriptCore/runtime/IntlCollator.h create mode 100644 Source/JavaScriptCore/runtime/IntlCollatorConstructor.cpp create mode 100644 Source/JavaScriptCore/runtime/IntlCollatorConstructor.h create mode 100644 Source/JavaScriptCore/runtime/IntlCollatorPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/IntlCollatorPrototype.h create mode 100644 Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp create mode 100644 Source/JavaScriptCore/runtime/IntlDateTimeFormat.h create mode 100644 Source/JavaScriptCore/runtime/IntlDateTimeFormatConstructor.cpp create mode 100644 Source/JavaScriptCore/runtime/IntlDateTimeFormatConstructor.h create mode 100644 Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/IntlDateTimeFormatPrototype.h create mode 100644 Source/JavaScriptCore/runtime/IntlNumberFormat.cpp create mode 100644 Source/JavaScriptCore/runtime/IntlNumberFormat.h create mode 100644 Source/JavaScriptCore/runtime/IntlNumberFormatConstructor.cpp create mode 100644 Source/JavaScriptCore/runtime/IntlNumberFormatConstructor.h create mode 100644 Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/IntlNumberFormatPrototype.h create mode 100644 Source/JavaScriptCore/runtime/IntlObject.cpp create mode 100644 Source/JavaScriptCore/runtime/IntlObject.h create mode 100644 Source/JavaScriptCore/runtime/IterationStatus.h create mode 100644 Source/JavaScriptCore/runtime/IteratorOperations.cpp create mode 100644 Source/JavaScriptCore/runtime/IteratorOperations.h create mode 100644 Source/JavaScriptCore/runtime/IteratorPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/IteratorPrototype.h delete mode 100644 Source/JavaScriptCore/runtime/JSActivation.cpp delete mode 100644 Source/JavaScriptCore/runtime/JSActivation.h create mode 100644 Source/JavaScriptCore/runtime/JSArrayBuffer.cpp create mode 100644 Source/JavaScriptCore/runtime/JSArrayBuffer.h create mode 100644 Source/JavaScriptCore/runtime/JSArrayBufferConstructor.cpp create mode 100644 Source/JavaScriptCore/runtime/JSArrayBufferConstructor.h create mode 100644 Source/JavaScriptCore/runtime/JSArrayBufferPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/JSArrayBufferPrototype.h create mode 100644 Source/JavaScriptCore/runtime/JSArrayBufferView.cpp create mode 100644 Source/JavaScriptCore/runtime/JSArrayBufferView.h create mode 100644 Source/JavaScriptCore/runtime/JSArrayBufferViewInlines.h create mode 100644 Source/JavaScriptCore/runtime/JSArrayIterator.cpp create mode 100644 Source/JavaScriptCore/runtime/JSArrayIterator.h create mode 100644 Source/JavaScriptCore/runtime/JSBoundSlotBaseFunction.cpp create mode 100644 Source/JavaScriptCore/runtime/JSBoundSlotBaseFunction.h create mode 100644 Source/JavaScriptCore/runtime/JSCInlines.h create mode 100644 Source/JavaScriptCore/runtime/JSCallee.cpp create mode 100644 Source/JavaScriptCore/runtime/JSCallee.h delete mode 100644 Source/JavaScriptCore/runtime/JSChunk.cpp delete mode 100644 Source/JavaScriptCore/runtime/JSChunk.h create mode 100644 Source/JavaScriptCore/runtime/JSConsole.cpp create mode 100644 Source/JavaScriptCore/runtime/JSConsole.h create mode 100644 Source/JavaScriptCore/runtime/JSDataView.cpp create mode 100644 Source/JavaScriptCore/runtime/JSDataView.h create mode 100644 Source/JavaScriptCore/runtime/JSDataViewPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/JSDataViewPrototype.h create mode 100644 Source/JavaScriptCore/runtime/JSEnvironmentRecord.cpp create mode 100644 Source/JavaScriptCore/runtime/JSEnvironmentRecord.h create mode 100644 Source/JavaScriptCore/runtime/JSFloat32Array.h create mode 100644 Source/JavaScriptCore/runtime/JSFloat64Array.h create mode 100644 Source/JavaScriptCore/runtime/JSGeneratorFunction.cpp create mode 100644 Source/JavaScriptCore/runtime/JSGeneratorFunction.h create mode 100644 Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h create mode 100644 Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructor.h create mode 100644 Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h create mode 100644 Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h create mode 100644 Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototype.h create mode 100644 Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h create mode 100644 Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeInlines.h create mode 100644 Source/JavaScriptCore/runtime/JSGlobalLexicalEnvironment.cpp create mode 100644 Source/JavaScriptCore/runtime/JSGlobalLexicalEnvironment.h create mode 100644 Source/JavaScriptCore/runtime/JSGlobalObjectDebuggable.cpp create mode 100644 Source/JavaScriptCore/runtime/JSGlobalObjectDebuggable.h create mode 100644 Source/JavaScriptCore/runtime/JSInt16Array.h create mode 100644 Source/JavaScriptCore/runtime/JSInt32Array.h create mode 100644 Source/JavaScriptCore/runtime/JSInt8Array.h create mode 100644 Source/JavaScriptCore/runtime/JSInternalPromise.cpp create mode 100644 Source/JavaScriptCore/runtime/JSInternalPromise.h create mode 100644 Source/JavaScriptCore/runtime/JSInternalPromiseConstructor.cpp create mode 100644 Source/JavaScriptCore/runtime/JSInternalPromiseConstructor.h create mode 100644 Source/JavaScriptCore/runtime/JSInternalPromiseDeferred.cpp create mode 100644 Source/JavaScriptCore/runtime/JSInternalPromiseDeferred.h create mode 100644 Source/JavaScriptCore/runtime/JSInternalPromisePrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/JSInternalPromisePrototype.h create mode 100644 Source/JavaScriptCore/runtime/JSJob.cpp create mode 100644 Source/JavaScriptCore/runtime/JSJob.h create mode 100644 Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp create mode 100644 Source/JavaScriptCore/runtime/JSLexicalEnvironment.h create mode 100644 Source/JavaScriptCore/runtime/JSMap.cpp create mode 100644 Source/JavaScriptCore/runtime/JSMap.h create mode 100644 Source/JavaScriptCore/runtime/JSMapIterator.cpp create mode 100644 Source/JavaScriptCore/runtime/JSMapIterator.h create mode 100644 Source/JavaScriptCore/runtime/JSModuleEnvironment.cpp create mode 100644 Source/JavaScriptCore/runtime/JSModuleEnvironment.h create mode 100644 Source/JavaScriptCore/runtime/JSModuleNamespaceObject.cpp create mode 100644 Source/JavaScriptCore/runtime/JSModuleNamespaceObject.h create mode 100644 Source/JavaScriptCore/runtime/JSModuleRecord.cpp create mode 100644 Source/JavaScriptCore/runtime/JSModuleRecord.h delete mode 100644 Source/JavaScriptCore/runtime/JSNameScope.cpp delete mode 100644 Source/JavaScriptCore/runtime/JSNameScope.h create mode 100644 Source/JavaScriptCore/runtime/JSNativeStdFunction.cpp create mode 100644 Source/JavaScriptCore/runtime/JSNativeStdFunction.h create mode 100644 Source/JavaScriptCore/runtime/JSObjectInlines.h create mode 100644 Source/JavaScriptCore/runtime/JSPromise.cpp create mode 100644 Source/JavaScriptCore/runtime/JSPromise.h create mode 100644 Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp create mode 100644 Source/JavaScriptCore/runtime/JSPromiseConstructor.h create mode 100644 Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp create mode 100644 Source/JavaScriptCore/runtime/JSPromiseDeferred.h create mode 100644 Source/JavaScriptCore/runtime/JSPromisePrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/JSPromisePrototype.h create mode 100644 Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp create mode 100644 Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h create mode 100644 Source/JavaScriptCore/runtime/JSSet.cpp create mode 100644 Source/JavaScriptCore/runtime/JSSet.h create mode 100644 Source/JavaScriptCore/runtime/JSSetIterator.cpp create mode 100644 Source/JavaScriptCore/runtime/JSSetIterator.h delete mode 100644 Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp delete mode 100644 Source/JavaScriptCore/runtime/JSStaticScopeObject.h create mode 100644 Source/JavaScriptCore/runtime/JSStringIterator.cpp create mode 100644 Source/JavaScriptCore/runtime/JSStringIterator.h create mode 100644 Source/JavaScriptCore/runtime/JSTemplateRegistryKey.cpp create mode 100644 Source/JavaScriptCore/runtime/JSTemplateRegistryKey.h create mode 100644 Source/JavaScriptCore/runtime/JSTypedArrayConstructors.cpp create mode 100644 Source/JavaScriptCore/runtime/JSTypedArrayConstructors.h create mode 100644 Source/JavaScriptCore/runtime/JSTypedArrayPrototypes.cpp create mode 100644 Source/JavaScriptCore/runtime/JSTypedArrayPrototypes.h create mode 100644 Source/JavaScriptCore/runtime/JSTypedArrayViewConstructor.cpp create mode 100644 Source/JavaScriptCore/runtime/JSTypedArrayViewConstructor.h create mode 100644 Source/JavaScriptCore/runtime/JSTypedArrayViewPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/JSTypedArrayViewPrototype.h create mode 100644 Source/JavaScriptCore/runtime/JSTypedArrays.cpp create mode 100644 Source/JavaScriptCore/runtime/JSTypedArrays.h create mode 100644 Source/JavaScriptCore/runtime/JSUint16Array.h create mode 100644 Source/JavaScriptCore/runtime/JSUint32Array.h create mode 100644 Source/JavaScriptCore/runtime/JSUint8Array.h create mode 100644 Source/JavaScriptCore/runtime/JSUint8ClampedArray.h delete mode 100644 Source/JavaScriptCore/runtime/JSVariableObject.cpp delete mode 100644 Source/JavaScriptCore/runtime/JSVariableObject.h create mode 100644 Source/JavaScriptCore/runtime/JSWeakMap.cpp create mode 100644 Source/JavaScriptCore/runtime/JSWeakMap.h create mode 100644 Source/JavaScriptCore/runtime/JSWeakSet.cpp create mode 100644 Source/JavaScriptCore/runtime/JSWeakSet.h create mode 100644 Source/JavaScriptCore/runtime/MapConstructor.cpp create mode 100644 Source/JavaScriptCore/runtime/MapConstructor.h create mode 100644 Source/JavaScriptCore/runtime/MapData.h create mode 100644 Source/JavaScriptCore/runtime/MapDataInlines.h create mode 100644 Source/JavaScriptCore/runtime/MapIteratorPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/MapIteratorPrototype.h create mode 100644 Source/JavaScriptCore/runtime/MapPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/MapPrototype.h create mode 100644 Source/JavaScriptCore/runtime/MathCommon.cpp create mode 100644 Source/JavaScriptCore/runtime/MathCommon.h create mode 100644 Source/JavaScriptCore/runtime/Microtask.h create mode 100644 Source/JavaScriptCore/runtime/ModuleLoaderObject.cpp create mode 100644 Source/JavaScriptCore/runtime/ModuleLoaderObject.h delete mode 100644 Source/JavaScriptCore/runtime/NameConstructor.cpp delete mode 100644 Source/JavaScriptCore/runtime/NameConstructor.h delete mode 100644 Source/JavaScriptCore/runtime/NameInstance.cpp delete mode 100644 Source/JavaScriptCore/runtime/NameInstance.h delete mode 100644 Source/JavaScriptCore/runtime/NamePrototype.cpp delete mode 100644 Source/JavaScriptCore/runtime/NamePrototype.h create mode 100644 Source/JavaScriptCore/runtime/NativeStdFunctionCell.cpp create mode 100644 Source/JavaScriptCore/runtime/NativeStdFunctionCell.h create mode 100644 Source/JavaScriptCore/runtime/NullGetterFunction.cpp create mode 100644 Source/JavaScriptCore/runtime/NullGetterFunction.h create mode 100644 Source/JavaScriptCore/runtime/NullSetterFunction.cpp create mode 100644 Source/JavaScriptCore/runtime/NullSetterFunction.h delete mode 100644 Source/JavaScriptCore/runtime/PropertyNameArray.cpp create mode 100644 Source/JavaScriptCore/runtime/ProxyConstructor.cpp create mode 100644 Source/JavaScriptCore/runtime/ProxyConstructor.h create mode 100644 Source/JavaScriptCore/runtime/ProxyObject.cpp create mode 100644 Source/JavaScriptCore/runtime/ProxyObject.h create mode 100644 Source/JavaScriptCore/runtime/PureNaN.h create mode 100644 Source/JavaScriptCore/runtime/ReflectObject.cpp create mode 100644 Source/JavaScriptCore/runtime/ReflectObject.h create mode 100644 Source/JavaScriptCore/runtime/RuntimeFlags.h create mode 100644 Source/JavaScriptCore/runtime/RuntimeType.cpp create mode 100644 Source/JavaScriptCore/runtime/RuntimeType.h create mode 100644 Source/JavaScriptCore/runtime/SamplingProfiler.cpp create mode 100644 Source/JavaScriptCore/runtime/SamplingProfiler.h create mode 100644 Source/JavaScriptCore/runtime/ScopeOffset.cpp create mode 100644 Source/JavaScriptCore/runtime/ScopeOffset.h create mode 100644 Source/JavaScriptCore/runtime/ScopedArguments.cpp create mode 100644 Source/JavaScriptCore/runtime/ScopedArguments.h create mode 100644 Source/JavaScriptCore/runtime/ScopedArgumentsTable.cpp create mode 100644 Source/JavaScriptCore/runtime/ScopedArgumentsTable.h create mode 100644 Source/JavaScriptCore/runtime/SetConstructor.cpp create mode 100644 Source/JavaScriptCore/runtime/SetConstructor.h create mode 100644 Source/JavaScriptCore/runtime/SetIteratorPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/SetIteratorPrototype.h create mode 100644 Source/JavaScriptCore/runtime/SetPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/SetPrototype.h create mode 100644 Source/JavaScriptCore/runtime/SimpleTypedArrayController.cpp create mode 100644 Source/JavaScriptCore/runtime/SimpleTypedArrayController.h create mode 100644 Source/JavaScriptCore/runtime/SlowPathReturnType.h create mode 100644 Source/JavaScriptCore/runtime/StackAlignment.h create mode 100644 Source/JavaScriptCore/runtime/StringIteratorPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/StringIteratorPrototype.h create mode 100644 Source/JavaScriptCore/runtime/StructureIDBlob.h create mode 100644 Source/JavaScriptCore/runtime/StructureIDTable.cpp create mode 100644 Source/JavaScriptCore/runtime/StructureIDTable.h create mode 100644 Source/JavaScriptCore/runtime/Symbol.cpp create mode 100644 Source/JavaScriptCore/runtime/Symbol.h create mode 100644 Source/JavaScriptCore/runtime/SymbolConstructor.cpp create mode 100644 Source/JavaScriptCore/runtime/SymbolConstructor.h create mode 100644 Source/JavaScriptCore/runtime/SymbolObject.cpp create mode 100644 Source/JavaScriptCore/runtime/SymbolObject.h create mode 100644 Source/JavaScriptCore/runtime/SymbolPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/SymbolPrototype.h create mode 100644 Source/JavaScriptCore/runtime/TemplateRegistry.cpp create mode 100644 Source/JavaScriptCore/runtime/TemplateRegistry.h create mode 100644 Source/JavaScriptCore/runtime/TemplateRegistryKey.h create mode 100644 Source/JavaScriptCore/runtime/TestRunnerUtils.cpp create mode 100644 Source/JavaScriptCore/runtime/TestRunnerUtils.h create mode 100644 Source/JavaScriptCore/runtime/ToNativeFromValue.h create mode 100644 Source/JavaScriptCore/runtime/TypeLocationCache.cpp create mode 100644 Source/JavaScriptCore/runtime/TypeLocationCache.h create mode 100644 Source/JavaScriptCore/runtime/TypeProfiler.cpp create mode 100644 Source/JavaScriptCore/runtime/TypeProfiler.h create mode 100644 Source/JavaScriptCore/runtime/TypeProfilerLog.cpp create mode 100644 Source/JavaScriptCore/runtime/TypeProfilerLog.h create mode 100644 Source/JavaScriptCore/runtime/TypeSet.cpp create mode 100644 Source/JavaScriptCore/runtime/TypeSet.h create mode 100644 Source/JavaScriptCore/runtime/TypedArrayAdaptors.h create mode 100644 Source/JavaScriptCore/runtime/TypedArrayBase.h create mode 100644 Source/JavaScriptCore/runtime/TypedArrayController.cpp create mode 100644 Source/JavaScriptCore/runtime/TypedArrayController.h delete mode 100644 Source/JavaScriptCore/runtime/TypedArrayDescriptor.h create mode 100644 Source/JavaScriptCore/runtime/TypedArrayInlines.h create mode 100644 Source/JavaScriptCore/runtime/TypedArrayType.cpp create mode 100644 Source/JavaScriptCore/runtime/TypedArrayType.h create mode 100644 Source/JavaScriptCore/runtime/TypedArrays.h create mode 100644 Source/JavaScriptCore/runtime/TypeofType.cpp create mode 100644 Source/JavaScriptCore/runtime/TypeofType.h create mode 100644 Source/JavaScriptCore/runtime/Uint16Array.h create mode 100644 Source/JavaScriptCore/runtime/Uint32Array.h create mode 100644 Source/JavaScriptCore/runtime/Uint8Array.h create mode 100644 Source/JavaScriptCore/runtime/Uint8ClampedArray.h create mode 100644 Source/JavaScriptCore/runtime/VMEntryScope.cpp create mode 100644 Source/JavaScriptCore/runtime/VMEntryScope.h create mode 100644 Source/JavaScriptCore/runtime/VMInlines.h delete mode 100644 Source/JavaScriptCore/runtime/VMStackBounds.h create mode 100644 Source/JavaScriptCore/runtime/VarOffset.cpp create mode 100644 Source/JavaScriptCore/runtime/VarOffset.h create mode 100644 Source/JavaScriptCore/runtime/WeakGCMapInlines.h create mode 100644 Source/JavaScriptCore/runtime/WeakMapConstructor.cpp create mode 100644 Source/JavaScriptCore/runtime/WeakMapConstructor.h create mode 100644 Source/JavaScriptCore/runtime/WeakMapData.cpp create mode 100644 Source/JavaScriptCore/runtime/WeakMapData.h create mode 100644 Source/JavaScriptCore/runtime/WeakMapPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/WeakMapPrototype.h delete mode 100644 Source/JavaScriptCore/runtime/WeakRandom.h create mode 100644 Source/JavaScriptCore/runtime/WeakSetConstructor.cpp create mode 100644 Source/JavaScriptCore/runtime/WeakSetConstructor.h create mode 100644 Source/JavaScriptCore/runtime/WeakSetPrototype.cpp create mode 100644 Source/JavaScriptCore/runtime/WeakSetPrototype.h create mode 100644 Source/JavaScriptCore/runtime/WriteBarrierInlines.h (limited to 'Source/JavaScriptCore/runtime') diff --git a/Source/JavaScriptCore/runtime/ArgList.cpp b/Source/JavaScriptCore/runtime/ArgList.cpp index 74240418c..3023151bf 100644 --- a/Source/JavaScriptCore/runtime/ArgList.cpp +++ b/Source/JavaScriptCore/runtime/ArgList.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2016 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -24,7 +24,7 @@ #include "HeapRootVisitor.h" #include "JSCJSValue.h" #include "JSObject.h" -#include "Operations.h" +#include "JSCInlines.h" using std::min; @@ -37,7 +37,7 @@ void ArgList::getSlice(int startIndex, ArgList& result) const return; } - result.m_args = m_args - startIndex; + result.m_args = m_args + startIndex; result.m_argCount = m_argCount - startIndex; } @@ -53,13 +53,14 @@ void MarkedArgumentBuffer::markLists(HeapRootVisitor& heapRootVisitor, ListSet& void MarkedArgumentBuffer::slowAppend(JSValue v) { - int newCapacity = m_capacity * 4; - EncodedJSValue* newBuffer = &(new EncodedJSValue[newCapacity])[newCapacity - 1]; + int newCapacity = (Checked(m_capacity) * 2).unsafeGet(); + size_t size = (Checked(newCapacity) * sizeof(EncodedJSValue)).unsafeGet(); + EncodedJSValue* newBuffer = static_cast(fastMalloc(size)); for (int i = 0; i < m_capacity; ++i) - newBuffer[-i] = m_buffer[-i]; + newBuffer[i] = m_buffer[i]; if (EncodedJSValue* base = mallocBase()) - delete [] base; + fastFree(base); m_buffer = newBuffer; m_capacity = newCapacity; diff --git a/Source/JavaScriptCore/runtime/ArgList.h b/Source/JavaScriptCore/runtime/ArgList.h index 84a0cdd8b..8ae622d07 100644 --- a/Source/JavaScriptCore/runtime/ArgList.h +++ b/Source/JavaScriptCore/runtime/ArgList.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2007, 2008, 2009, 2016 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -46,7 +46,7 @@ public: MarkedArgumentBuffer() : m_size(0) , m_capacity(inlineCapacity) - , m_buffer(&m_inlineBuffer[m_capacity - 1]) + , m_buffer(m_inlineBuffer) , m_markSet(0) { } @@ -57,7 +57,7 @@ public: m_markSet->remove(this); if (EncodedJSValue* base = mallocBase()) - delete [] base; + fastFree(base); } size_t size() const { return m_size; } @@ -104,14 +104,14 @@ private: EncodedJSValue& slotFor(int item) const { - return m_buffer[-item]; + return m_buffer[item]; } EncodedJSValue* mallocBase() { if (m_capacity == static_cast(inlineCapacity)) return 0; - return &slotFor(m_capacity - 1); + return &slotFor(0); } int m_size; @@ -119,26 +119,10 @@ private: EncodedJSValue m_inlineBuffer[inlineCapacity]; EncodedJSValue* m_buffer; ListSet* m_markSet; - -private: - // Prohibits new / delete, which would break GC. - void* operator new(size_t size) - { - return fastMalloc(size); - } - void operator delete(void* p) - { - fastFree(p); - } - - void* operator new[](size_t); - void operator delete[](void*); - - void* operator new(size_t, void*); - void operator delete(void*, size_t); }; class ArgList { + friend class Interpreter; friend class JIT; public: ArgList() @@ -163,7 +147,7 @@ public: { if (i >= m_argCount) return jsUndefined(); - return m_args[-i]; + return m_args[i]; } bool isEmpty() const { return !m_argCount; } @@ -172,6 +156,8 @@ public: JS_EXPORT_PRIVATE void getSlice(int startIndex, ArgList& result) const; private: + JSValue* data() const { return m_args; } + JSValue* m_args; int m_argCount; }; diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp deleted file mode 100644 index a188885e6..000000000 --- a/Source/JavaScriptCore/runtime/Arguments.cpp +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) - * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) - * Copyright (C) 2007 Maks Orlovich - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" -#include "Arguments.h" - -#include "JSActivation.h" -#include "JSFunction.h" -#include "JSGlobalObject.h" -#include "Operations.h" - -using namespace std; - -namespace JSC { - -const ClassInfo Arguments::s_info = { "Arguments", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Arguments) }; - -void Arguments::visitChildren(JSCell* cell, SlotVisitor& visitor) -{ - Arguments* thisObject = jsCast(cell); - ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); - COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); - ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - JSObject::visitChildren(thisObject, visitor); - - if (thisObject->m_registerArray) - visitor.appendValues(thisObject->m_registerArray.get(), thisObject->m_numArguments); - visitor.append(&thisObject->m_callee); - visitor.append(&thisObject->m_activation); -} - -void Arguments::destroy(JSCell* cell) -{ - static_cast(cell)->Arguments::~Arguments(); -} - -void Arguments::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t length) -{ - if (UNLIKELY(m_overrodeLength)) { - length = min(get(exec, exec->propertyNames().length).toUInt32(exec), length); - for (unsigned i = 0; i < length; i++) - callFrame->setArgument(i, get(exec, i)); - return; - } - ASSERT(length == this->length(exec)); - for (size_t i = 0; i < length; ++i) { - if (JSValue value = tryGetArgument(i)) - callFrame->setArgument(i, value); - else - callFrame->setArgument(i, get(exec, i)); - } -} - -void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args) -{ - if (UNLIKELY(m_overrodeLength)) { - unsigned length = get(exec, exec->propertyNames().length).toUInt32(exec); - for (unsigned i = 0; i < length; i++) - args.append(get(exec, i)); - return; - } - uint32_t length = this->length(exec); - for (size_t i = 0; i < length; ++i) { - if (JSValue value = tryGetArgument(i)) - args.append(value); - else - args.append(get(exec, i)); - } -} - -bool Arguments::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned i, PropertySlot& slot) -{ - Arguments* thisObject = jsCast(cell); - if (JSValue value = thisObject->tryGetArgument(i)) { - slot.setValue(value); - return true; - } - - return JSObject::getOwnPropertySlot(thisObject, exec, Identifier(exec, String::number(i)), slot); -} - -void Arguments::createStrictModeCallerIfNecessary(ExecState* exec) -{ - if (m_overrodeCaller) - return; - - m_overrodeCaller = true; - PropertyDescriptor descriptor; - descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Accessor); - methodTable()->defineOwnProperty(this, exec, exec->propertyNames().caller, descriptor, false); -} - -void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec) -{ - if (m_overrodeCallee) - return; - - m_overrodeCallee = true; - PropertyDescriptor descriptor; - descriptor.setAccessorDescriptor(globalObject()->throwTypeErrorGetterSetter(exec), DontEnum | DontDelete | Accessor); - methodTable()->defineOwnProperty(this, exec, exec->propertyNames().callee, descriptor, false); -} - -bool Arguments::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot) -{ - Arguments* thisObject = jsCast(cell); - unsigned i = propertyName.asIndex(); - if (JSValue value = thisObject->tryGetArgument(i)) { - RELEASE_ASSERT(i < PropertyName::NotAnIndex); - slot.setValue(value); - return true; - } - - if (propertyName == exec->propertyNames().length && LIKELY(!thisObject->m_overrodeLength)) { - slot.setValue(jsNumber(thisObject->m_numArguments)); - return true; - } - - if (propertyName == exec->propertyNames().callee && LIKELY(!thisObject->m_overrodeCallee)) { - if (!thisObject->m_isStrictMode) { - slot.setValue(thisObject->m_callee.get()); - return true; - } - thisObject->createStrictModeCalleeIfNecessary(exec); - } - - if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) - thisObject->createStrictModeCallerIfNecessary(exec); - - return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot); -} - -bool Arguments::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) -{ - Arguments* thisObject = jsCast(object); - unsigned i = propertyName.asIndex(); - if (JSValue value = thisObject->tryGetArgument(i)) { - RELEASE_ASSERT(i < PropertyName::NotAnIndex); - descriptor.setDescriptor(value, None); - return true; - } - - if (propertyName == exec->propertyNames().length && LIKELY(!thisObject->m_overrodeLength)) { - descriptor.setDescriptor(jsNumber(thisObject->m_numArguments), DontEnum); - return true; - } - - if (propertyName == exec->propertyNames().callee && LIKELY(!thisObject->m_overrodeCallee)) { - if (!thisObject->m_isStrictMode) { - descriptor.setDescriptor(thisObject->m_callee.get(), DontEnum); - return true; - } - thisObject->createStrictModeCalleeIfNecessary(exec); - } - - if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) - thisObject->createStrictModeCallerIfNecessary(exec); - - return JSObject::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); -} - -void Arguments::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) -{ - Arguments* thisObject = jsCast(object); - for (unsigned i = 0; i < thisObject->m_numArguments; ++i) { - if (!thisObject->isArgument(i)) - continue; - propertyNames.add(Identifier(exec, String::number(i))); - } - if (mode == IncludeDontEnumProperties) { - propertyNames.add(exec->propertyNames().callee); - propertyNames.add(exec->propertyNames().length); - } - JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode); -} - -void Arguments::putByIndex(JSCell* cell, ExecState* exec, unsigned i, JSValue value, bool shouldThrow) -{ - Arguments* thisObject = jsCast(cell); - if (thisObject->trySetArgument(exec->vm(), i, value)) - return; - - PutPropertySlot slot(shouldThrow); - JSObject::put(thisObject, exec, Identifier(exec, String::number(i)), value, slot); -} - -void Arguments::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) -{ - Arguments* thisObject = jsCast(cell); - unsigned i = propertyName.asIndex(); - if (thisObject->trySetArgument(exec->vm(), i, value)) - return; - - if (propertyName == exec->propertyNames().length && !thisObject->m_overrodeLength) { - thisObject->m_overrodeLength = true; - thisObject->putDirect(exec->vm(), propertyName, value, DontEnum); - return; - } - - if (propertyName == exec->propertyNames().callee && !thisObject->m_overrodeCallee) { - if (!thisObject->m_isStrictMode) { - thisObject->m_overrodeCallee = true; - thisObject->putDirect(exec->vm(), propertyName, value, DontEnum); - return; - } - thisObject->createStrictModeCalleeIfNecessary(exec); - } - - if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) - thisObject->createStrictModeCallerIfNecessary(exec); - - JSObject::put(thisObject, exec, propertyName, value, slot); -} - -bool Arguments::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i) -{ - Arguments* thisObject = jsCast(cell); - if (i < thisObject->m_numArguments) { - if (!Base::deletePropertyByIndex(cell, exec, i)) - return false; - if (thisObject->tryDeleteArgument(i)) - return true; - } - return JSObject::deletePropertyByIndex(thisObject, exec, i); -} - -bool Arguments::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) -{ - if (exec->vm().isInDefineOwnProperty()) - return Base::deleteProperty(cell, exec, propertyName); - - Arguments* thisObject = jsCast(cell); - unsigned i = propertyName.asIndex(); - if (i < thisObject->m_numArguments) { - RELEASE_ASSERT(i < PropertyName::NotAnIndex); - if (!Base::deleteProperty(cell, exec, propertyName)) - return false; - if (thisObject->tryDeleteArgument(i)) - return true; - } - - if (propertyName == exec->propertyNames().length && !thisObject->m_overrodeLength) { - thisObject->m_overrodeLength = true; - return true; - } - - if (propertyName == exec->propertyNames().callee && !thisObject->m_overrodeCallee) { - if (!thisObject->m_isStrictMode) { - thisObject->m_overrodeCallee = true; - return true; - } - thisObject->createStrictModeCalleeIfNecessary(exec); - } - - if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) - thisObject->createStrictModeCallerIfNecessary(exec); - - return JSObject::deleteProperty(thisObject, exec, propertyName); -} - -bool Arguments::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor, bool shouldThrow) -{ - Arguments* thisObject = jsCast(object); - unsigned i = propertyName.asIndex(); - if (i < thisObject->m_numArguments) { - RELEASE_ASSERT(i < PropertyName::NotAnIndex); - // If the property is not yet present on the object, and is not yet marked as deleted, then add it now. - PropertySlot slot; - if (!thisObject->isDeletedArgument(i) && !JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot)) { - JSValue value = thisObject->tryGetArgument(i); - ASSERT(value); - object->putDirectMayBeIndex(exec, propertyName, value); - } - if (!Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow)) - return false; - - // From ES 5.1, 10.6 Arguments Object - // 5. If the value of isMapped is not undefined, then - if (thisObject->isArgument(i)) { - // a. If IsAccessorDescriptor(Desc) is true, then - if (descriptor.isAccessorDescriptor()) { - // i. Call the [[Delete]] internal method of map passing P, and false as the arguments. - thisObject->tryDeleteArgument(i); - } else { // b. Else - // i. If Desc.[[Value]] is present, then - // 1. Call the [[Put]] internal method of map passing P, Desc.[[Value]], and Throw as the arguments. - if (descriptor.value()) - thisObject->trySetArgument(exec->vm(), i, descriptor.value()); - // ii. If Desc.[[Writable]] is present and its value is false, then - // 1. Call the [[Delete]] internal method of map passing P and false as arguments. - if (descriptor.writablePresent() && !descriptor.writable()) - thisObject->tryDeleteArgument(i); - } - } - return true; - } - - if (propertyName == exec->propertyNames().length && !thisObject->m_overrodeLength) { - thisObject->putDirect(exec->vm(), propertyName, jsNumber(thisObject->m_numArguments), DontEnum); - thisObject->m_overrodeLength = true; - } else if (propertyName == exec->propertyNames().callee && !thisObject->m_overrodeCallee) { - thisObject->putDirect(exec->vm(), propertyName, thisObject->m_callee.get(), DontEnum); - thisObject->m_overrodeCallee = true; - } else if (propertyName == exec->propertyNames().caller && thisObject->m_isStrictMode) - thisObject->createStrictModeCallerIfNecessary(exec); - - return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow); -} - -void Arguments::tearOff(CallFrame* callFrame) -{ - if (isTornOff()) - return; - - if (!m_numArguments) - return; - - // Must be called for the same call frame from which it was created. - ASSERT(bitwise_cast*>(callFrame) == m_registers); - - m_registerArray = adoptArrayPtr(new WriteBarrier[m_numArguments]); - m_registers = m_registerArray.get() + CallFrame::offsetFor(m_numArguments + 1); - - // If we have a captured argument that logically aliases activation storage, - // but we optimize away the activation, the argument needs to tear off into - // our storage. The simplest way to do this is to revert it to Normal status. - if (m_slowArguments && !m_activation) { - for (size_t i = 0; i < m_numArguments; ++i) { - if (m_slowArguments[i].status != SlowArgument::Captured) - continue; - m_slowArguments[i].status = SlowArgument::Normal; - m_slowArguments[i].index = CallFrame::argumentOffset(i); - } - } - - if (!callFrame->isInlineCallFrame()) { - for (size_t i = 0; i < m_numArguments; ++i) - trySetArgument(callFrame->vm(), i, callFrame->argumentAfterCapture(i)); - return; - } - - tearOffForInlineCallFrame( - callFrame->vm(), callFrame->registers(), callFrame->inlineCallFrame()); -} - -void Arguments::didTearOffActivation(ExecState* exec, JSActivation* activation) -{ - RELEASE_ASSERT(activation); - if (isTornOff()) - return; - - if (!m_numArguments) - return; - - m_activation.set(exec->vm(), this, activation); - tearOff(exec); -} - -void Arguments::tearOff(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) -{ - if (isTornOff()) - return; - - if (!m_numArguments) - return; - - m_registerArray = adoptArrayPtr(new WriteBarrier[m_numArguments]); - m_registers = m_registerArray.get() + CallFrame::offsetFor(m_numArguments + 1); - - tearOffForInlineCallFrame( - callFrame->vm(), callFrame->registers() + inlineCallFrame->stackOffset, - inlineCallFrame); -} - -void Arguments::tearOffForInlineCallFrame(VM& vm, Register* registers, InlineCallFrame* inlineCallFrame) -{ - for (size_t i = 0; i < m_numArguments; ++i) { - ValueRecovery& recovery = inlineCallFrame->arguments[i + 1]; - // In the future we'll support displaced recoveries (indicating that the - // argument was flushed to a different location), but for now we don't do - // that so this code will fail if that were to happen. On the other hand, - // it's much less likely that we'll support in-register recoveries since - // this code does not (easily) have access to registers. - JSValue value; - Register* location = ®isters[CallFrame::argumentOffset(i)]; - switch (recovery.technique()) { - case AlreadyInJSStack: - value = location->jsValue(); - break; - case AlreadyInJSStackAsUnboxedInt32: - value = jsNumber(location->unboxedInt32()); - break; - case AlreadyInJSStackAsUnboxedCell: - value = location->unboxedCell(); - break; - case AlreadyInJSStackAsUnboxedBoolean: - value = jsBoolean(location->unboxedBoolean()); - break; - case AlreadyInJSStackAsUnboxedDouble: -#if USE(JSVALUE64) - value = jsNumber(*bitwise_cast(location)); -#else - value = location->jsValue(); -#endif - break; - case Constant: - value = recovery.constant(); - break; - default: - RELEASE_ASSERT_NOT_REACHED(); - break; - } - trySetArgument(vm, i, value); - } -} - -} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h deleted file mode 100644 index 58ac782b6..000000000 --- a/Source/JavaScriptCore/runtime/Arguments.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) - * Copyright (C) 2007 Maks Orlovich - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef Arguments_h -#define Arguments_h - -#include "CodeOrigin.h" -#include "JSActivation.h" -#include "JSDestructibleObject.h" -#include "JSFunction.h" -#include "JSGlobalObject.h" -#include "Interpreter.h" -#include "ObjectConstructor.h" - -namespace JSC { - -class Arguments : public JSDestructibleObject { - friend class JIT; - friend class DFG::SpeculativeJIT; -public: - typedef JSDestructibleObject Base; - - static Arguments* create(VM& vm, CallFrame* callFrame) - { - Arguments* arguments = new (NotNull, allocateCell(vm.heap)) Arguments(callFrame); - arguments->finishCreation(callFrame); - return arguments; - } - - static Arguments* create(VM& vm, CallFrame* callFrame, InlineCallFrame* inlineCallFrame) - { - Arguments* arguments = new (NotNull, allocateCell(vm.heap)) Arguments(callFrame); - arguments->finishCreation(callFrame, inlineCallFrame); - return arguments; - } - - enum { MaxArguments = 0x10000 }; - -private: - enum NoParametersType { NoParameters }; - - Arguments(CallFrame*); - Arguments(CallFrame*, NoParametersType); - - void tearOffForInlineCallFrame(VM& vm, Register*, InlineCallFrame*); - -public: - static const ClassInfo s_info; - - static void visitChildren(JSCell*, SlotVisitor&); - - void fillArgList(ExecState*, MarkedArgumentBuffer&); - - uint32_t length(ExecState* exec) const - { - if (UNLIKELY(m_overrodeLength)) - return get(exec, exec->propertyNames().length).toUInt32(exec); - return m_numArguments; - } - - void copyToArguments(ExecState*, CallFrame*, uint32_t length); - void tearOff(CallFrame*); - void tearOff(CallFrame*, InlineCallFrame*); - bool isTornOff() const { return m_registerArray; } - void didTearOffActivation(ExecState*, JSActivation*); - - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) - { - return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); - } - -protected: - static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags; - - void finishCreation(CallFrame*); - void finishCreation(CallFrame*, InlineCallFrame*); - -private: - static void destroy(JSCell*); - static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&); - static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); - static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); - static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); - static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); - static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); - static bool deleteProperty(JSCell*, ExecState*, PropertyName); - static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); - static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow); - void createStrictModeCallerIfNecessary(ExecState*); - void createStrictModeCalleeIfNecessary(ExecState*); - - bool isArgument(size_t); - bool trySetArgument(VM&, size_t argument, JSValue); - JSValue tryGetArgument(size_t argument); - bool isDeletedArgument(size_t); - bool tryDeleteArgument(size_t); - WriteBarrierBase& argument(size_t); - void allocateSlowArguments(); - - void init(CallFrame*); - - WriteBarrier m_activation; - - unsigned m_numArguments; - - // We make these full byte booleans to make them easy to test from the JIT, - // and because even if they were single-bit booleans we still wouldn't save - // any space. - bool m_overrodeLength; - bool m_overrodeCallee; - bool m_overrodeCaller; - bool m_isStrictMode; - - WriteBarrierBase* m_registers; - OwnArrayPtr > m_registerArray; - - OwnArrayPtr m_slowArguments; - - WriteBarrier m_callee; -}; - -Arguments* asArguments(JSValue); - -inline Arguments* asArguments(JSValue value) -{ - ASSERT(asObject(value)->inherits(&Arguments::s_info)); - return static_cast(asObject(value)); -} - -inline Arguments::Arguments(CallFrame* callFrame) - : JSDestructibleObject(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure()) -{ -} - -inline Arguments::Arguments(CallFrame* callFrame, NoParametersType) - : JSDestructibleObject(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure()) -{ -} - -inline void Arguments::allocateSlowArguments() -{ - if (m_slowArguments) - return; - m_slowArguments = adoptArrayPtr(new SlowArgument[m_numArguments]); - for (size_t i = 0; i < m_numArguments; ++i) { - ASSERT(m_slowArguments[i].status == SlowArgument::Normal); - m_slowArguments[i].index = CallFrame::argumentOffset(i); - } -} - -inline bool Arguments::tryDeleteArgument(size_t argument) -{ - if (!isArgument(argument)) - return false; - allocateSlowArguments(); - m_slowArguments[argument].status = SlowArgument::Deleted; - return true; -} - -inline bool Arguments::trySetArgument(VM& vm, size_t argument, JSValue value) -{ - if (!isArgument(argument)) - return false; - this->argument(argument).set(vm, this, value); - return true; -} - -inline JSValue Arguments::tryGetArgument(size_t argument) -{ - if (!isArgument(argument)) - return JSValue(); - return this->argument(argument).get(); -} - -inline bool Arguments::isDeletedArgument(size_t argument) -{ - if (argument >= m_numArguments) - return false; - if (!m_slowArguments) - return false; - if (m_slowArguments[argument].status != SlowArgument::Deleted) - return false; - return true; -} - -inline bool Arguments::isArgument(size_t argument) -{ - if (argument >= m_numArguments) - return false; - if (m_slowArguments && m_slowArguments[argument].status == SlowArgument::Deleted) - return false; - return true; -} - -inline WriteBarrierBase& Arguments::argument(size_t argument) -{ - ASSERT(isArgument(argument)); - if (!m_slowArguments) - return m_registers[CallFrame::argumentOffset(argument)]; - - int index = m_slowArguments[argument].index; - if (!m_activation || m_slowArguments[argument].status != SlowArgument::Captured) - return m_registers[index]; - - return m_activation->registerAt(index); -} - -inline void Arguments::finishCreation(CallFrame* callFrame) -{ - Base::finishCreation(callFrame->vm()); - ASSERT(inherits(&s_info)); - - JSFunction* callee = jsCast(callFrame->callee()); - m_numArguments = callFrame->argumentCount(); - m_registers = reinterpret_cast*>(callFrame->registers()); - m_callee.set(callFrame->vm(), this, callee); - m_overrodeLength = false; - m_overrodeCallee = false; - m_overrodeCaller = false; - m_isStrictMode = callFrame->codeBlock()->isStrictMode(); - - SharedSymbolTable* symbolTable = callFrame->codeBlock()->symbolTable(); - const SlowArgument* slowArguments = symbolTable->slowArguments(); - if (slowArguments) { - allocateSlowArguments(); - size_t count = std::min(m_numArguments, symbolTable->parameterCount()); - for (size_t i = 0; i < count; ++i) - m_slowArguments[i] = slowArguments[i]; - } - - // The bytecode generator omits op_tear_off_activation in cases of no - // declared parameters, so we need to tear off immediately. - if (m_isStrictMode || !callee->jsExecutable()->parameterCount()) - tearOff(callFrame); -} - -inline void Arguments::finishCreation(CallFrame* callFrame, InlineCallFrame* inlineCallFrame) -{ - Base::finishCreation(callFrame->vm()); - ASSERT(inherits(&s_info)); - - JSFunction* callee = inlineCallFrame->calleeForCallFrame(callFrame); - m_numArguments = inlineCallFrame->arguments.size() - 1; - m_registers = reinterpret_cast*>(callFrame->registers()) + inlineCallFrame->stackOffset; - m_callee.set(callFrame->vm(), this, callee); - m_overrodeLength = false; - m_overrodeCallee = false; - m_overrodeCaller = false; - m_isStrictMode = jsCast(inlineCallFrame->executable.get())->isStrictMode(); - ASSERT(!jsCast(inlineCallFrame->executable.get())->symbolTable(inlineCallFrame->isCall ? CodeForCall : CodeForConstruct)->slowArguments()); - - // The bytecode generator omits op_tear_off_activation in cases of no - // declared parameters, so we need to tear off immediately. - if (m_isStrictMode || !callee->jsExecutable()->parameterCount()) - tearOff(callFrame, inlineCallFrame); -} - -} // namespace JSC - -#endif // Arguments_h diff --git a/Source/JavaScriptCore/runtime/ArgumentsMode.h b/Source/JavaScriptCore/runtime/ArgumentsMode.h new file mode 100644 index 000000000..67cd3348d --- /dev/null +++ b/Source/JavaScriptCore/runtime/ArgumentsMode.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#ifndef ArgumentsMode_h +#define ArgumentsMode_h + +namespace JSC { + +enum class ArgumentsMode { + Cloned, + FakeValues +}; + +} // namespace JSC + +#endif // ArgumentsMode_h + diff --git a/Source/JavaScriptCore/runtime/ArityCheckMode.h b/Source/JavaScriptCore/runtime/ArityCheckMode.h new file mode 100644 index 000000000..f2090c057 --- /dev/null +++ b/Source/JavaScriptCore/runtime/ArityCheckMode.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#ifndef ArityCheckMode_h +#define ArityCheckMode_h + +namespace JSC { + +enum ArityCheckMode { + ArityCheckNotRequired, + MustCheckArity +}; + +} // namespace JSC + +#endif // ArityCheckMode_h + diff --git a/Source/JavaScriptCore/runtime/ArrayBuffer.cpp b/Source/JavaScriptCore/runtime/ArrayBuffer.cpp new file mode 100644 index 000000000..5a7ad268e --- /dev/null +++ b/Source/JavaScriptCore/runtime/ArrayBuffer.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2009, 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#include "config.h" +#include "ArrayBuffer.h" + +#include "ArrayBufferNeuteringWatchpoint.h" +#include "JSArrayBufferView.h" +#include "JSCInlines.h" +#include + +namespace JSC { + +bool ArrayBuffer::transfer(ArrayBufferContents& result) +{ + Ref protect(*this); + + if (!m_contents.m_data) { + result.m_data = 0; + return false; + } + + bool isNeuterable = !m_pinCount; + + if (!isNeuterable) { + m_contents.copyTo(result); + if (!result.m_data) + return false; + return true; + } + + m_contents.transfer(result); + for (size_t i = numberOfIncomingReferences(); i--;) { + JSCell* cell = incomingReferenceAt(i); + if (JSArrayBufferView* view = jsDynamicCast(cell)) + view->neuter(); + else if (ArrayBufferNeuteringWatchpoint* watchpoint = jsDynamicCast(cell)) + watchpoint->fireAll(); + } + return true; +} + +} // namespace JSC + diff --git a/Source/JavaScriptCore/runtime/ArrayBuffer.h b/Source/JavaScriptCore/runtime/ArrayBuffer.h new file mode 100644 index 000000000..a7b6f33d7 --- /dev/null +++ b/Source/JavaScriptCore/runtime/ArrayBuffer.h @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2009, 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#ifndef ArrayBuffer_h +#define ArrayBuffer_h + +#include "GCIncomingRefCounted.h" +#include "Weak.h" +#include +#include +#include + +namespace JSC { + +class ArrayBuffer; +class ArrayBufferView; +class JSArrayBuffer; + +class ArrayBufferContents { + WTF_MAKE_NONCOPYABLE(ArrayBufferContents); +public: + ArrayBufferContents() + : m_data(0) + , m_sizeInBytes(0) + { } + + inline ~ArrayBufferContents(); + + void* data() { return m_data; } + unsigned sizeInBytes() { return m_sizeInBytes; } + +private: + ArrayBufferContents(void* data, unsigned sizeInBytes) + : m_data(data) + , m_sizeInBytes(sizeInBytes) + { } + + friend class ArrayBuffer; + + enum InitializationPolicy { + ZeroInitialize, + DontInitialize + }; + + static inline void tryAllocate(unsigned numElements, unsigned elementByteSize, InitializationPolicy, ArrayBufferContents&); + void transfer(ArrayBufferContents& other) + { + ASSERT(!other.m_data); + other.m_data = m_data; + other.m_sizeInBytes = m_sizeInBytes; + m_data = 0; + m_sizeInBytes = 0; + } + + void copyTo(ArrayBufferContents& other) + { + ASSERT(!other.m_data); + ArrayBufferContents::tryAllocate(m_sizeInBytes, sizeof(char), ArrayBufferContents::DontInitialize, other); + if (!other.m_data) + return; + memcpy(other.m_data, m_data, m_sizeInBytes); + other.m_sizeInBytes = m_sizeInBytes; + } + + void* m_data; + unsigned m_sizeInBytes; +}; + +class ArrayBuffer : public GCIncomingRefCounted { +public: + static inline PassRefPtr create(unsigned numElements, unsigned elementByteSize); + static inline PassRefPtr create(ArrayBuffer*); + static inline PassRefPtr create(const void* source, unsigned byteLength); + static inline PassRefPtr create(ArrayBufferContents&); + static inline PassRefPtr createAdopted(const void* data, unsigned byteLength); + + // Only for use by Uint8ClampedArray::createUninitialized and SharedBuffer::createArrayBuffer. + static inline PassRefPtr createUninitialized(unsigned numElements, unsigned elementByteSize); + + inline void* data(); + inline const void* data() const; + inline unsigned byteLength() const; + + inline size_t gcSizeEstimateInBytes() const; + + inline PassRefPtr slice(int begin, int end) const; + inline PassRefPtr slice(int begin) const; + + inline void pin(); + inline void unpin(); + + JS_EXPORT_PRIVATE bool transfer(ArrayBufferContents&); + bool isNeutered() { return !m_contents.m_data; } + + static ptrdiff_t offsetOfData() { return OBJECT_OFFSETOF(ArrayBuffer, m_contents) + OBJECT_OFFSETOF(ArrayBufferContents, m_data); } + + ~ArrayBuffer() { } + +private: + static inline PassRefPtr create(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy); + + inline ArrayBuffer(ArrayBufferContents&); + inline PassRefPtr sliceImpl(unsigned begin, unsigned end) const; + inline unsigned clampIndex(int index) const; + static inline int clampValue(int x, int left, int right); + + unsigned m_pinCount; + ArrayBufferContents m_contents; + +public: + Weak m_wrapper; +}; + +int ArrayBuffer::clampValue(int x, int left, int right) +{ + ASSERT(left <= right); + if (x < left) + x = left; + if (right < x) + x = right; + return x; +} + +PassRefPtr ArrayBuffer::create(unsigned numElements, unsigned elementByteSize) +{ + return create(numElements, elementByteSize, ArrayBufferContents::ZeroInitialize); +} + +PassRefPtr ArrayBuffer::create(ArrayBuffer* other) +{ + return ArrayBuffer::create(other->data(), other->byteLength()); +} + +PassRefPtr ArrayBuffer::create(const void* source, unsigned byteLength) +{ + ArrayBufferContents contents; + ArrayBufferContents::tryAllocate(byteLength, 1, ArrayBufferContents::ZeroInitialize, contents); + if (!contents.m_data) + return 0; + RefPtr buffer = adoptRef(new ArrayBuffer(contents)); + ASSERT(!byteLength || source); + memcpy(buffer->data(), source, byteLength); + return buffer.release(); +} + +PassRefPtr ArrayBuffer::create(ArrayBufferContents& contents) +{ + return adoptRef(new ArrayBuffer(contents)); +} + +PassRefPtr ArrayBuffer::createAdopted(const void* data, unsigned byteLength) +{ + ArrayBufferContents contents(const_cast(data), byteLength); + return create(contents); +} + +PassRefPtr ArrayBuffer::createUninitialized(unsigned numElements, unsigned elementByteSize) +{ + return create(numElements, elementByteSize, ArrayBufferContents::DontInitialize); +} + +PassRefPtr ArrayBuffer::create(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy) +{ + ArrayBufferContents contents; + ArrayBufferContents::tryAllocate(numElements, elementByteSize, policy, contents); + if (!contents.m_data) + return 0; + return adoptRef(new ArrayBuffer(contents)); +} + +ArrayBuffer::ArrayBuffer(ArrayBufferContents& contents) + : m_pinCount(0) +{ + contents.transfer(m_contents); +} + +void* ArrayBuffer::data() +{ + return m_contents.m_data; +} + +const void* ArrayBuffer::data() const +{ + return m_contents.m_data; +} + +unsigned ArrayBuffer::byteLength() const +{ + return m_contents.m_sizeInBytes; +} + +size_t ArrayBuffer::gcSizeEstimateInBytes() const +{ + return sizeof(ArrayBuffer) + static_cast(byteLength()); +} + +PassRefPtr ArrayBuffer::slice(int begin, int end) const +{ + return sliceImpl(clampIndex(begin), clampIndex(end)); +} + +PassRefPtr ArrayBuffer::slice(int begin) const +{ + return sliceImpl(clampIndex(begin), byteLength()); +} + +PassRefPtr ArrayBuffer::sliceImpl(unsigned begin, unsigned end) const +{ + unsigned size = begin <= end ? end - begin : 0; + return ArrayBuffer::create(static_cast(data()) + begin, size); +} + +unsigned ArrayBuffer::clampIndex(int index) const +{ + unsigned currentLength = byteLength(); + if (index < 0) + index = currentLength + index; + return clampValue(index, 0, currentLength); +} + +void ArrayBuffer::pin() +{ + m_pinCount++; +} + +void ArrayBuffer::unpin() +{ + m_pinCount--; +} + +void ArrayBufferContents::tryAllocate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents::InitializationPolicy policy, ArrayBufferContents& result) +{ + // Do not allow 31-bit overflow of the total size. + if (numElements) { + unsigned totalSize = numElements * elementByteSize; + if (totalSize / numElements != elementByteSize + || totalSize > static_cast(std::numeric_limits::max())) { + result.m_data = 0; + return; + } + } + bool allocationSucceeded = false; + if (policy == ZeroInitialize) + allocationSucceeded = WTF::tryFastCalloc(numElements, elementByteSize).getValue(result.m_data); + else { + ASSERT(policy == DontInitialize); + allocationSucceeded = WTF::tryFastMalloc(numElements * elementByteSize).getValue(result.m_data); + } + + if (allocationSucceeded) { + result.m_sizeInBytes = numElements * elementByteSize; + return; + } + result.m_data = 0; +} + +ArrayBufferContents::~ArrayBufferContents() +{ + WTF::fastFree(m_data); +} + +} // namespace JSC + +using JSC::ArrayBuffer; + +#endif // ArrayBuffer_h + diff --git a/Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.cpp b/Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.cpp new file mode 100644 index 000000000..a15b50440 --- /dev/null +++ b/Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#include "config.h" +#include "ArrayBufferNeuteringWatchpoint.h" + +#include "JSCInlines.h" + +namespace JSC { + +const ClassInfo ArrayBufferNeuteringWatchpoint::s_info = { + "ArrayBufferNeuteringWatchpoint", 0, 0, + CREATE_METHOD_TABLE(ArrayBufferNeuteringWatchpoint) +}; + +ArrayBufferNeuteringWatchpoint::ArrayBufferNeuteringWatchpoint(VM& vm) + : Base(vm, vm.arrayBufferNeuteringWatchpointStructure.get()) + , m_set(adoptRef(new WatchpointSet(IsWatched))) +{ +} + +void ArrayBufferNeuteringWatchpoint::destroy(JSCell* cell) +{ + static_cast(cell)->ArrayBufferNeuteringWatchpoint::~ArrayBufferNeuteringWatchpoint(); +} + +ArrayBufferNeuteringWatchpoint* ArrayBufferNeuteringWatchpoint::create(VM& vm) +{ + ArrayBufferNeuteringWatchpoint* result = new + (NotNull, allocateCell(vm.heap)) + ArrayBufferNeuteringWatchpoint(vm); + result->finishCreation(vm); + return result; +} + +Structure* ArrayBufferNeuteringWatchpoint::createStructure(VM& vm) +{ + return Structure::create(vm, 0, jsNull(), TypeInfo(CellType, StructureFlags), info()); +} + +void ArrayBufferNeuteringWatchpoint::fireAll() +{ + set()->fireAll("Array buffer was neutered"); +} + +} // namespace JSC + diff --git a/Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.h b/Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.h new file mode 100644 index 000000000..ab26f0332 --- /dev/null +++ b/Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#ifndef ArrayBufferNeuteringWatchpoint_h +#define ArrayBufferNeuteringWatchpoint_h + +#include "JSCell.h" +#include "Watchpoint.h" + +namespace JSC { + +class ArrayBufferNeuteringWatchpoint final : public JSCell { +public: + typedef JSCell Base; + static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; + + DECLARE_INFO; + + static ArrayBufferNeuteringWatchpoint* create(VM&); + + static const bool needsDestruction = true; + static void destroy(JSCell*); + + static Structure* createStructure(VM&); + + WatchpointSet* set() { return m_set.get(); } + + void fireAll(); + +private: + explicit ArrayBufferNeuteringWatchpoint(VM&); + + RefPtr m_set; +}; + +} // namespace JSC + +#endif // ArrayBufferNeuteringWatchpoint_h diff --git a/Source/JavaScriptCore/runtime/ArrayBufferView.cpp b/Source/JavaScriptCore/runtime/ArrayBufferView.cpp new file mode 100644 index 000000000..f0fe06be4 --- /dev/null +++ b/Source/JavaScriptCore/runtime/ArrayBufferView.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#include "config.h" +#include "ArrayBufferView.h" + +#include "ArrayBuffer.h" + +namespace JSC { + +ArrayBufferView::ArrayBufferView( + PassRefPtr buffer, + unsigned byteOffset) + : m_byteOffset(byteOffset) + , m_isNeuterable(true) + , m_buffer(buffer) +{ + m_baseAddress = m_buffer ? (static_cast(m_buffer->data()) + m_byteOffset) : 0; +} + +ArrayBufferView::~ArrayBufferView() +{ + if (!m_isNeuterable) + m_buffer->unpin(); +} + +void ArrayBufferView::setNeuterable(bool flag) +{ + if (flag == m_isNeuterable) + return; + + m_isNeuterable = flag; + + if (!m_buffer) + return; + + if (flag) + m_buffer->unpin(); + else + m_buffer->pin(); +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ArrayBufferView.h b/Source/JavaScriptCore/runtime/ArrayBufferView.h new file mode 100644 index 000000000..3fc10b0dd --- /dev/null +++ b/Source/JavaScriptCore/runtime/ArrayBufferView.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2009, 2013 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#ifndef ArrayBufferView_h +#define ArrayBufferView_h + +#include "ArrayBuffer.h" +#include "TypedArrayType.h" +#include +#include +#include +#include +#include + +namespace JSC { + +class JSArrayBufferView; +class JSGlobalObject; +class ExecState; + +class ArrayBufferView : public RefCounted { +public: + virtual TypedArrayType getType() const = 0; + + bool isNeutered() const + { + return !m_buffer || m_buffer->isNeutered(); + } + + PassRefPtr buffer() const + { + if (isNeutered()) + return 0; + return m_buffer; + } + + void* baseAddress() const + { + if (isNeutered()) + return 0; + return m_baseAddress; + } + + unsigned byteOffset() const + { + if (isNeutered()) + return 0; + return m_byteOffset; + } + + virtual unsigned byteLength() const = 0; + + JS_EXPORT_PRIVATE void setNeuterable(bool flag); + bool isNeuterable() const { return m_isNeuterable; } + + JS_EXPORT_PRIVATE virtual ~ArrayBufferView(); + + // Helper to verify byte offset is size aligned. + static bool verifyByteOffsetAlignment(unsigned byteOffset, size_t size) + { + return !(byteOffset & (size - 1)); + } + + // Helper to verify that a given sub-range of an ArrayBuffer is + // within range. + static bool verifySubRangeLength(PassRefPtr buffer, unsigned byteOffset, unsigned numElements, size_t size) + { + unsigned byteLength = buffer->byteLength(); + if (byteOffset > byteLength) + return false; + unsigned remainingElements = (byteLength - byteOffset) / size; + if (numElements > remainingElements) + return false; + return true; + } + + virtual JSArrayBufferView* wrap(ExecState*, JSGlobalObject*) = 0; + +protected: + JS_EXPORT_PRIVATE ArrayBufferView(PassRefPtr, unsigned byteOffset); + + inline bool setImpl(ArrayBufferView*, unsigned byteOffset); + + inline bool setRangeImpl(const char* data, size_t dataByteLength, unsigned byteOffset); + + inline bool zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength); + + static inline void calculateOffsetAndLength( + int start, int end, unsigned arraySize, + unsigned* offset, unsigned* length); + + // Input offset is in number of elements from this array's view; + // output offset is in number of bytes from the underlying buffer's view. + template + static void clampOffsetAndNumElements( + PassRefPtr buffer, + unsigned arrayByteOffset, + unsigned *offset, + unsigned *numElements) + { + unsigned maxOffset = (UINT_MAX - arrayByteOffset) / sizeof(T); + if (*offset > maxOffset) { + *offset = buffer->byteLength(); + *numElements = 0; + return; + } + *offset = arrayByteOffset + *offset * sizeof(T); + *offset = std::min(buffer->byteLength(), *offset); + unsigned remainingElements = (buffer->byteLength() - *offset) / sizeof(T); + *numElements = std::min(remainingElements, *numElements); + } + + // This is the address of the ArrayBuffer's storage, plus the byte offset. + void* m_baseAddress; + + unsigned m_byteOffset : 31; + bool m_isNeuterable : 1; + +private: + friend class ArrayBuffer; + RefPtr m_buffer; +}; + +bool ArrayBufferView::setImpl(ArrayBufferView* array, unsigned byteOffset) +{ + if (byteOffset > byteLength() + || byteOffset + array->byteLength() > byteLength() + || byteOffset + array->byteLength() < byteOffset) { + // Out of range offset or overflow + return false; + } + + char* base = static_cast(baseAddress()); + memmove(base + byteOffset, array->baseAddress(), array->byteLength()); + return true; +} + +bool ArrayBufferView::setRangeImpl(const char* data, size_t dataByteLength, unsigned byteOffset) +{ + if (byteOffset > byteLength() + || byteOffset + dataByteLength > byteLength() + || byteOffset + dataByteLength < byteOffset) { + // Out of range offset or overflow + return false; + } + + char* base = static_cast(baseAddress()); + memmove(base + byteOffset, data, dataByteLength); + return true; +} + +bool ArrayBufferView::zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength) +{ + if (byteOffset > byteLength() + || byteOffset + rangeByteLength > byteLength() + || byteOffset + rangeByteLength < byteOffset) { + // Out of range offset or overflow + return false; + } + + char* base = static_cast(baseAddress()); + memset(base + byteOffset, 0, rangeByteLength); + return true; +} + +void ArrayBufferView::calculateOffsetAndLength( + int start, int end, unsigned arraySize, unsigned* offset, unsigned* length) +{ + if (start < 0) + start += arraySize; + if (start < 0) + start = 0; + if (end < 0) + end += arraySize; + if (end < 0) + end = 0; + if (static_cast(end) > arraySize) + end = arraySize; + if (end < start) + end = start; + *offset = static_cast(start); + *length = static_cast(end - start); +} + +} // namespace JSC + +using JSC::ArrayBufferView; + +#endif // ArrayBufferView_h diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp index 752055716..cf02ea324 100644 --- a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp @@ -29,10 +29,11 @@ #include "CopiedSpaceInlines.h" #include "Error.h" #include "ExceptionHelpers.h" +#include "GetterSetter.h" #include "JSArray.h" #include "JSFunction.h" #include "Lookup.h" -#include "Operations.h" +#include "JSCInlines.h" namespace JSC { @@ -44,67 +45,65 @@ static EncodedJSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*); namespace JSC { -ASSERT_HAS_TRIVIAL_DESTRUCTOR(ArrayConstructor); +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ArrayConstructor); -const ClassInfo ArrayConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::arrayConstructorTable, CREATE_METHOD_TABLE(ArrayConstructor) }; +const ClassInfo ArrayConstructor::s_info = { "Function", &InternalFunction::s_info, &arrayConstructorTable, CREATE_METHOD_TABLE(ArrayConstructor) }; /* Source for ArrayConstructor.lut.h @begin arrayConstructorTable isArray arrayConstructorIsArray DontEnum|Function 1 + of JSBuiltin DontEnum|Function 0 + from JSBuiltin DontEnum|Function 0 @end */ -ArrayConstructor::ArrayConstructor(JSGlobalObject* globalObject, Structure* structure) - : InternalFunction(globalObject, structure) +ArrayConstructor::ArrayConstructor(VM& vm, Structure* structure) + : InternalFunction(vm, structure) { } -void ArrayConstructor::finishCreation(ExecState* exec, ArrayPrototype* arrayPrototype) +void ArrayConstructor::finishCreation(VM& vm, ArrayPrototype* arrayPrototype, GetterSetter* speciesSymbol) { - Base::finishCreation(exec->vm(), arrayPrototype->classInfo()->className); - putDirectWithoutTransition(exec->vm(), exec->propertyNames().prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly); - putDirectWithoutTransition(exec->vm(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete); + Base::finishCreation(vm, arrayPrototype->classInfo()->className); + putDirectWithoutTransition(vm, vm.propertyNames->prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly); + putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontEnum | DontDelete); + putDirectNonIndexAccessor(vm, vm.propertyNames->speciesSymbol, speciesSymbol, Accessor | ReadOnly | DontEnum); } -bool ArrayConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot &slot) +bool ArrayConstructor::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot &slot) { - return getStaticFunctionSlot(exec, ExecState::arrayConstructorTable(exec), jsCast(cell), propertyName, slot); -} - -bool ArrayConstructor::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) -{ - return getStaticFunctionDescriptor(exec, ExecState::arrayConstructorTable(exec), jsCast(object), propertyName, descriptor); + return getStaticFunctionSlot(exec, arrayConstructorTable, jsCast(object), propertyName, slot); } // ------------------------------ Functions --------------------------- -JSObject* constructArrayWithSizeQuirk(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, JSValue length) +JSObject* constructArrayWithSizeQuirk(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, JSValue length, JSValue newTarget) { if (!length.isNumber()) - return constructArray(exec, profile, globalObject, &length, 1); + return constructArrayNegativeIndexed(exec, profile, globalObject, &length, 1, newTarget); uint32_t n = length.toUInt32(exec); if (n != length.toNumber(exec)) - return throwError(exec, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))); - return constructEmptyArray(exec, profile, globalObject, n); + return exec->vm().throwException(exec, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))); + return constructEmptyArray(exec, profile, globalObject, n, newTarget); } -static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args) +static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args, JSValue newTarget) { JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject(); // a single numeric argument denotes the array size (!) if (args.size() == 1) - return constructArrayWithSizeQuirk(exec, 0, globalObject, args.at(0)); + return constructArrayWithSizeQuirk(exec, nullptr, globalObject, args.at(0), newTarget); // otherwise the array is constructed with the arguments in it - return constructArray(exec, 0, globalObject, args); + return constructArray(exec, nullptr, globalObject, args, newTarget); } static EncodedJSValue JSC_HOST_CALL constructWithArrayConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructArrayWithSizeQuirk(exec, args)); + return JSValue::encode(constructArrayWithSizeQuirk(exec, args, exec->newTarget())); } ConstructType ArrayConstructor::getConstructData(JSCell*, ConstructData& constructData) @@ -116,7 +115,7 @@ ConstructType ArrayConstructor::getConstructData(JSCell*, ConstructData& constru static EncodedJSValue JSC_HOST_CALL callArrayConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructArrayWithSizeQuirk(exec, args)); + return JSValue::encode(constructArrayWithSizeQuirk(exec, args, JSValue())); } CallType ArrayConstructor::getCallData(JSCell*, CallData& callData) @@ -128,7 +127,7 @@ CallType ArrayConstructor::getCallData(JSCell*, CallData& callData) EncodedJSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState* exec) { - return JSValue::encode(jsBoolean(exec->argument(0).inherits(&JSArray::s_info))); + return JSValue::encode(jsBoolean(exec->argument(0).inherits(JSArray::info()))); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.h b/Source/JavaScriptCore/runtime/ArrayConstructor.h index 727475b47..5256a52da 100644 --- a/Source/JavaScriptCore/runtime/ArrayConstructor.h +++ b/Source/JavaScriptCore/runtime/ArrayConstructor.h @@ -28,40 +28,39 @@ namespace JSC { class ArrayAllocationProfile; class ArrayPrototype; class JSArray; +class GetterSetter; class ArrayConstructor : public InternalFunction { public: typedef InternalFunction Base; + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags; - static ArrayConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ArrayPrototype* arrayPrototype) + static ArrayConstructor* create(VM& vm, Structure* structure, ArrayPrototype* arrayPrototype, GetterSetter* speciesSymbol) { - ArrayConstructor* constructor = new (NotNull, allocateCell(*exec->heap())) ArrayConstructor(globalObject, structure); - constructor->finishCreation(exec, arrayPrototype); + ArrayConstructor* constructor = new (NotNull, allocateCell(vm.heap)) ArrayConstructor(vm, structure); + constructor->finishCreation(vm, arrayPrototype, speciesSymbol); return constructor; } - static const ClassInfo s_info; + DECLARE_INFO; static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); } protected: - void finishCreation(ExecState*, ArrayPrototype*); - static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags; + void finishCreation(VM&, ArrayPrototype*, GetterSetter* speciesSymbol); private: - ArrayConstructor(JSGlobalObject*, Structure*); - static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&); - - static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); + ArrayConstructor(VM&, Structure*); + static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); static ConstructType getConstructData(JSCell*, ConstructData&); static CallType getCallData(JSCell*, CallData&); }; -JSObject* constructArrayWithSizeQuirk(ExecState*, ArrayAllocationProfile*, JSGlobalObject*, JSValue); +JSObject* constructArrayWithSizeQuirk(ExecState*, ArrayAllocationProfile*, JSGlobalObject*, JSValue length, JSValue prototype = JSValue()); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ArrayConventions.h b/Source/JavaScriptCore/runtime/ArrayConventions.h index e5ef96336..9c62ea9b8 100644 --- a/Source/JavaScriptCore/runtime/ArrayConventions.h +++ b/Source/JavaScriptCore/runtime/ArrayConventions.h @@ -38,7 +38,7 @@ namespace JSC { // (specifically, this is only one property - the value 0xFFFFFFFFU as an unsigned 32-bit // integer) are not considered array indices and will be stored in the JSObject property map. // -// All properties with a numeric identifer, representable as an unsigned integer i, +// All properties with a numeric identifier, representable as an unsigned integer i, // where (i <= MAX_ARRAY_INDEX), are an array index and will be stored in either the // storage vector or the sparse map. An array index i will be handled in the following // fashion: @@ -58,7 +58,14 @@ namespace JSC { // These values have to be macros to be used in max() and min() without introducing // a PIC branch in Mach-O binaries, see . + +// If you grow an ArrayStorage array by more than this, then the array will go sparse. Note that we +// could probably make this smaller (it's large because it used to be conflated with +// MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH). #define MIN_SPARSE_ARRAY_INDEX 100000U +// If you try to allocate a contiguous array larger than this, then we will allocate an ArrayStorage +// array instead. We allow for an array that occupies 1GB of VM. +#define MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH 1024 * 1024 * 1024 / 8 #define MAX_STORAGE_VECTOR_INDEX (MAX_STORAGE_VECTOR_LENGTH - 1) // 0xFFFFFFFF is a bit weird -- is not an array index even though it's an integer. #define MAX_ARRAY_INDEX 0xFFFFFFFEU diff --git a/Source/JavaScriptCore/runtime/ArrayIteratorPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayIteratorPrototype.cpp new file mode 100644 index 000000000..132469d04 --- /dev/null +++ b/Source/JavaScriptCore/runtime/ArrayIteratorPrototype.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2013 Apple, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#include "config.h" +#include "ArrayIteratorPrototype.h" + +namespace JSC { + +} + +#include "ArrayIteratorPrototype.lut.h" + +#include "IteratorOperations.h" +#include "JSArrayIterator.h" +#include "JSCInlines.h" +#include "JSCJSValueInlines.h" +#include "JSCellInlines.h" +#include "JSGlobalObject.h" +#include "ObjectConstructor.h" +#include "StructureInlines.h" + +namespace JSC { + + +const ClassInfo ArrayIteratorPrototype::s_info = { "Array Iterator", &Base::s_info, &arrayIteratorPrototypeTable, CREATE_METHOD_TABLE(ArrayIteratorPrototype) }; + +/* Source for ArrayIteratorPrototype.lut.h +@begin arrayIteratorPrototypeTable + next JSBuiltin DontEnum|Function 0 +@end +*/ + +void ArrayIteratorPrototype::finishCreation(VM& vm, JSGlobalObject*) +{ + Base::finishCreation(vm); + ASSERT(inherits(info())); + putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Array Iterator"), DontEnum | ReadOnly); + vm.prototypeMap.addPrototype(this); +} + +bool ArrayIteratorPrototype::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) +{ + return getStaticFunctionSlot(exec, arrayIteratorPrototypeTable, jsCast(object), propertyName, slot); +} + +// ------------------------------ Array Functions ---------------------------- + +} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ArrayIteratorPrototype.h b/Source/JavaScriptCore/runtime/ArrayIteratorPrototype.h new file mode 100644 index 000000000..2b234f8ee --- /dev/null +++ b/Source/JavaScriptCore/runtime/ArrayIteratorPrototype.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2013 Apple, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#ifndef ArrayIteratorPrototype_h +#define ArrayIteratorPrototype_h + +#include "JSObject.h" + +namespace JSC { + +class ArrayIteratorPrototype : public JSNonFinalObject { +public: + typedef JSNonFinalObject Base; + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | Base::StructureFlags; + + static ArrayIteratorPrototype* create(VM& vm, JSGlobalObject* globalObject, Structure* structure) + { + ArrayIteratorPrototype* prototype = new (NotNull, allocateCell(vm.heap)) ArrayIteratorPrototype(vm, structure); + prototype->finishCreation(vm, globalObject); + return prototype; + } + + DECLARE_INFO; + + static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); + } + +private: + ArrayIteratorPrototype(VM& vm, Structure* structure) + : Base(vm, structure) + { + } + + void finishCreation(VM&, JSGlobalObject*); + static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); +}; + +} + +#endif // !defined(ArrayIteratorPrototype_h) diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index ba1c7b725..ae1a6c28a 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2007, 2008, 2009, 2011, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2007-2009, 2011, 2013, 2015-2016 Apple Inc. All rights reserved. * Copyright (C) 2003 Peter Kelly (pmk@post.com) * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) * @@ -24,6 +24,9 @@ #include "config.h" #include "ArrayPrototype.h" +#include "AdaptiveInferredPropertyValueWatchpointBase.h" +#include "ArrayConstructor.h" +#include "BuiltinNames.h" #include "ButterflyInlines.h" #include "CachedCall.h" #include "CodeBlock.h" @@ -31,11 +34,14 @@ #include "Error.h" #include "Interpreter.h" #include "JIT.h" +#include "JSArrayIterator.h" +#include "JSCBuiltins.h" +#include "JSCInlines.h" #include "JSStringBuilder.h" #include "JSStringJoiner.h" #include "Lookup.h" +#include "ObjectConstructor.h" #include "ObjectPrototype.h" -#include "Operations.h" #include "StringRecursionChecker.h" #include #include @@ -43,127 +49,180 @@ namespace JSC { -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState*); -static EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState*); - -} - -#include "ArrayPrototype.lut.h" - -namespace JSC { - -static inline bool isNumericCompareFunction(ExecState* exec, CallType callType, const CallData& callData) -{ - if (callType != CallTypeJS) - return false; - - FunctionExecutable* executable = callData.js.functionExecutable; - - JSObject* error = executable->compileForCall(exec, callData.js.scope); - if (error) - return false; - - return executable->generatedBytecodeForCall().isNumericCompareFunction(); -} +EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncKeys(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncEntries(ExecState*); // ------------------------------ ArrayPrototype ---------------------------- -const ClassInfo ArrayPrototype::s_info = {"Array", &JSArray::s_info, 0, ExecState::arrayPrototypeTable, CREATE_METHOD_TABLE(ArrayPrototype)}; - -/* Source for ArrayPrototype.lut.h -@begin arrayPrototypeTable 16 - toString arrayProtoFuncToString DontEnum|Function 0 - toLocaleString arrayProtoFuncToLocaleString DontEnum|Function 0 - concat arrayProtoFuncConcat DontEnum|Function 1 - join arrayProtoFuncJoin DontEnum|Function 1 - pop arrayProtoFuncPop DontEnum|Function 0 - push arrayProtoFuncPush DontEnum|Function 1 - reverse arrayProtoFuncReverse DontEnum|Function 0 - shift arrayProtoFuncShift DontEnum|Function 0 - slice arrayProtoFuncSlice DontEnum|Function 2 - sort arrayProtoFuncSort DontEnum|Function 1 - splice arrayProtoFuncSplice DontEnum|Function 2 - unshift arrayProtoFuncUnShift DontEnum|Function 1 - every arrayProtoFuncEvery DontEnum|Function 1 - forEach arrayProtoFuncForEach DontEnum|Function 1 - some arrayProtoFuncSome DontEnum|Function 1 - indexOf arrayProtoFuncIndexOf DontEnum|Function 1 - lastIndexOf arrayProtoFuncLastIndexOf DontEnum|Function 1 - filter arrayProtoFuncFilter DontEnum|Function 1 - reduce arrayProtoFuncReduce DontEnum|Function 1 - reduceRight arrayProtoFuncReduceRight DontEnum|Function 1 - map arrayProtoFuncMap DontEnum|Function 1 -@end -*/ - -ArrayPrototype* ArrayPrototype::create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure) +const ClassInfo ArrayPrototype::s_info = {"Array", &JSArray::s_info, nullptr, CREATE_METHOD_TABLE(ArrayPrototype)}; + +ArrayPrototype* ArrayPrototype::create(VM& vm, JSGlobalObject* globalObject, Structure* structure) { - ArrayPrototype* prototype = new (NotNull, allocateCell(*exec->heap())) ArrayPrototype(globalObject, structure); - prototype->finishCreation(globalObject); + ArrayPrototype* prototype = new (NotNull, allocateCell(vm.heap)) ArrayPrototype(vm, structure); + prototype->finishCreation(vm, globalObject); + vm.heap.addFinalizer(prototype, destroy); return prototype; } // ECMA 15.4.4 -ArrayPrototype::ArrayPrototype(JSGlobalObject* globalObject, Structure* structure) - : JSArray(globalObject->vm(), structure, 0) +ArrayPrototype::ArrayPrototype(VM& vm, Structure* structure) + : JSArray(vm, structure, 0) { } -void ArrayPrototype::finishCreation(JSGlobalObject* globalObject) +void ArrayPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject) { - VM& vm = globalObject->vm(); Base::finishCreation(vm); - ASSERT(inherits(&s_info)); + ASSERT(inherits(info())); vm.prototypeMap.addPrototype(this); -} -bool ArrayPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot) -{ - return getStaticFunctionSlot(exec, ExecState::arrayPrototypeTable(exec), jsCast(cell), propertyName, slot); + putDirectWithoutTransition(vm, vm.propertyNames->values, globalObject->arrayProtoValuesFunction(), DontEnum); + putDirectWithoutTransition(vm, vm.propertyNames->iteratorSymbol, globalObject->arrayProtoValuesFunction(), DontEnum); + + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toString, arrayProtoFuncToString, DontEnum, 0); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->toLocaleString, arrayProtoFuncToLocaleString, DontEnum, 0); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("concat", arrayProtoFuncConcat, DontEnum, 1); + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("fill", arrayPrototypeFillCodeGenerator, DontEnum); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->join, arrayProtoFuncJoin, DontEnum, 1); + JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION("pop", arrayProtoFuncPop, DontEnum, 0, ArrayPopIntrinsic); + JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().pushPublicName(), arrayProtoFuncPush, DontEnum, 1, ArrayPushIntrinsic); + JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().pushPrivateName(), arrayProtoFuncPush, DontEnum | DontDelete | ReadOnly, 1, ArrayPushIntrinsic); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("reverse", arrayProtoFuncReverse, DontEnum, 0); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().shiftPublicName(), arrayProtoFuncShift, DontEnum, 0); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().shiftPrivateName(), arrayProtoFuncShift, DontEnum | DontDelete | ReadOnly, 0); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->slice, arrayProtoFuncSlice, DontEnum, 2); + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("sort", arrayPrototypeSortCodeGenerator, DontEnum); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("splice", arrayProtoFuncSplice, DontEnum, 2); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("unshift", arrayProtoFuncUnShift, DontEnum, 1); + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("every", arrayPrototypeEveryCodeGenerator, DontEnum); + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("forEach", arrayPrototypeForEachCodeGenerator, DontEnum); + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("some", arrayPrototypeSomeCodeGenerator, DontEnum); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("indexOf", arrayProtoFuncIndexOf, DontEnum, 1); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("lastIndexOf", arrayProtoFuncLastIndexOf, DontEnum, 1); + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("filter", arrayPrototypeFilterCodeGenerator, DontEnum); + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("reduce", arrayPrototypeReduceCodeGenerator, DontEnum); + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("reduceRight", arrayPrototypeReduceRightCodeGenerator, DontEnum); + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("map", arrayPrototypeMapCodeGenerator, DontEnum); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->entries, arrayProtoFuncEntries, DontEnum, 0); + JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->keys, arrayProtoFuncKeys, DontEnum, 0); + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("find", arrayPrototypeFindCodeGenerator, DontEnum); + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("findIndex", arrayPrototypeFindIndexCodeGenerator, DontEnum); + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("includes", arrayPrototypeIncludesCodeGenerator, DontEnum); + JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("copyWithin", arrayPrototypeCopyWithinCodeGenerator, DontEnum); + + JSObject* unscopables = constructEmptyObject(globalObject->globalExec(), globalObject->nullPrototypeObjectStructure()); + const char* unscopableNames[] = { + "copyWithin", + "entries", + "fill", + "find", + "findIndex", + "keys", + "values" + }; + for (const char* unscopableName : unscopableNames) + unscopables->putDirect(vm, Identifier::fromString(&vm, unscopableName), jsBoolean(true)); + putDirectWithoutTransition(vm, vm.propertyNames->unscopablesSymbol, unscopables, DontEnum | ReadOnly); } -bool ArrayPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) +void ArrayPrototype::destroy(JSC::JSCell* cell) { - return getStaticFunctionDescriptor(exec, ExecState::arrayPrototypeTable(exec), jsCast(object), propertyName, descriptor); + ArrayPrototype* thisObject = static_cast(cell); + thisObject->ArrayPrototype::~ArrayPrototype(); } // ------------------------------ Array Functions ---------------------------- -// Helper function -static JSValue getProperty(ExecState* exec, JSObject* obj, unsigned index) +static ALWAYS_INLINE JSValue getProperty(ExecState* exec, JSObject* object, unsigned index) { - PropertySlot slot(obj); - if (!obj->getPropertySlot(exec, index, slot)) + if (JSValue result = object->tryGetIndexQuickly(index)) + return result; + PropertySlot slot(object, PropertySlot::InternalMethodType::Get); + if (!object->getPropertySlot(exec, index, slot)) return JSValue(); return slot.getValue(exec, index); } -static void putProperty(ExecState* exec, JSObject* obj, PropertyName propertyName, JSValue value) +static ALWAYS_INLINE unsigned getLength(ExecState* exec, JSObject* obj) +{ + if (isJSArray(obj)) + return jsCast(obj)->length(); + return obj->get(exec, exec->propertyNames().length).toUInt32(exec); +} + +static ALWAYS_INLINE void putLength(ExecState* exec, JSObject* obj, JSValue value) +{ + PutPropertySlot slot(obj); + obj->methodTable()->put(obj, exec, exec->propertyNames().length, value, slot); +} + +static ALWAYS_INLINE void setLength(ExecState* exec, JSObject* obj, unsigned value) { - PutPropertySlot slot; - obj->methodTable()->put(obj, exec, propertyName, value, slot); + if (isJSArray(obj)) + jsCast(obj)->setLength(exec, value); + putLength(exec, obj, jsNumber(value)); } -static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument, unsigned length, unsigned undefinedValue = 0) +enum class SpeciesConstructResult { + FastPath, + Exception, + CreatedObject +}; + +static ALWAYS_INLINE std::pair speciesConstructArray(ExecState* exec, JSObject* thisObject, unsigned length) +{ + // ECMA 9.4.2.3: https://tc39.github.io/ecma262/#sec-arrayspeciescreate + JSValue constructor = jsUndefined(); + if (LIKELY(isJSArray(thisObject))) { + // Fast path in the normal case where the user has not set an own constructor and the Array.prototype.constructor is normal. + // We need prototype check for subclasses of Array, which are Array objects but have a different prototype by default. + if (LIKELY(!thisObject->hasCustomProperties() + && thisObject->globalObject()->arrayPrototype() == thisObject->prototype() + && !thisObject->globalObject()->arrayPrototype()->didChangeConstructorOrSpeciesProperties())) + return std::make_pair(SpeciesConstructResult::FastPath, nullptr); + + constructor = thisObject->get(exec, exec->propertyNames().constructor); + if (exec->hadException()) + return std::make_pair(SpeciesConstructResult::Exception, nullptr); + if (constructor.isConstructor()) { + JSObject* constructorObject = jsCast(constructor); + if (exec->lexicalGlobalObject() != constructorObject->globalObject()) + return std::make_pair(SpeciesConstructResult::FastPath, nullptr);; + } + if (constructor.isObject()) { + constructor = constructor.get(exec, exec->propertyNames().speciesSymbol); + if (exec->hadException()) + return std::make_pair(SpeciesConstructResult::Exception, nullptr); + if (constructor.isNull()) + return std::make_pair(SpeciesConstructResult::FastPath, nullptr);; + } + } + if (constructor.isUndefined()) + return std::make_pair(SpeciesConstructResult::FastPath, nullptr);; + + MarkedArgumentBuffer args; + args.append(jsNumber(length)); + JSObject* newObject = construct(exec, constructor, args, "Species construction did not get a valid constructor"); + if (exec->hadException()) + return std::make_pair(SpeciesConstructResult::Exception, nullptr); + return std::make_pair(SpeciesConstructResult::CreatedObject, newObject); +} + +static inline unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument, unsigned length, unsigned undefinedValue = 0) { JSValue value = exec->argument(argument); if (value.isUndefined()) @@ -177,7 +236,6 @@ static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument return indexDouble > length ? length : static_cast(indexDouble); } - // The shift/unshift function implement the shift/unshift behaviour required // by the corresponding array prototype methods, and by splice. In both cases, // the methods are operating an an array or array like object. @@ -192,6 +250,7 @@ static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument // currentCount) will be shifted to the left or right as appropriate; in the // case of shift this must be removing values, in the case of unshift this // must be introducing new values. + template void shift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned currentCount, unsigned resultCount, unsigned length) { @@ -203,33 +262,32 @@ void shift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned current if (isJSArray(thisObj)) { JSArray* array = asArray(thisObj); - if (array->length() == length && asArray(thisObj)->shiftCount(exec, header, count)) + if (array->length() == length && array->shiftCount(exec, header, count)) return; } for (unsigned k = header; k < length - currentCount; ++k) { unsigned from = k + currentCount; unsigned to = k + resultCount; - PropertySlot slot(thisObj); - if (thisObj->getPropertySlot(exec, from, slot)) { - JSValue value = slot.getValue(exec, from); + if (JSValue value = getProperty(exec, thisObj, from)) { if (exec->hadException()) return; - thisObj->methodTable()->putByIndex(thisObj, exec, to, value, true); + thisObj->putByIndexInline(exec, to, value, true); if (exec->hadException()) return; - } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, to)) { + } else if (!thisObj->methodTable(exec->vm())->deletePropertyByIndex(thisObj, exec, to)) { throwTypeError(exec, ASCIILiteral("Unable to delete property.")); return; } } for (unsigned k = length; k > length - count; --k) { - if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1)) { + if (!thisObj->methodTable(exec->vm())->deletePropertyByIndex(thisObj, exec, k - 1)) { throwTypeError(exec, ASCIILiteral("Unable to delete property.")); return; } } } + template void unshift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned currentCount, unsigned resultCount, unsigned length) { @@ -250,17 +308,15 @@ void unshift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned curre if (array->length() == length && array->unshiftCount(exec, header, count)) return; } - + for (unsigned k = length - currentCount; k > header; --k) { unsigned from = k + currentCount - 1; unsigned to = k + resultCount - 1; - PropertySlot slot(thisObj); - if (thisObj->getPropertySlot(exec, from, slot)) { - JSValue value = slot.getValue(exec, from); + if (JSValue value = getProperty(exec, thisObj, from)) { if (exec->hadException()) return; - thisObj->methodTable()->putByIndex(thisObj, exec, to, value, true); - } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, to)) { + thisObj->putByIndexInline(exec, to, value, true); + } else if (!thisObj->methodTable(exec->vm())->deletePropertyByIndex(thisObj, exec, to)) { throwTypeError(exec, ASCIILiteral("Unable to delete property.")); return; } @@ -271,7 +327,7 @@ void unshift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned curre EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) { - JSValue thisValue = exec->hostThisValue(); + JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); // 1. Let array be the result of calling ToObject on the this value. JSObject* thisObject = thisValue.toObject(exec); @@ -283,291 +339,479 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) // 3. If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2). if (!function.isCell()) - return JSValue::encode(jsMakeNontrivialString(exec, "[object ", thisObject->methodTable()->className(thisObject), "]")); + return JSValue::encode(jsMakeNontrivialString(exec, "[object ", thisObject->methodTable(exec->vm())->className(thisObject), "]")); CallData callData; CallType callType = getCallData(function, callData); if (callType == CallTypeNone) - return JSValue::encode(jsMakeNontrivialString(exec, "[object ", thisObject->methodTable()->className(thisObject), "]")); + return JSValue::encode(jsMakeNontrivialString(exec, "[object ", thisObject->methodTable(exec->vm())->className(thisObject), "]")); // 4. Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list. if (!isJSArray(thisObject) || callType != CallTypeHost || callData.native.function != arrayProtoFuncJoin) return JSValue::encode(call(exec, function, callType, callData, thisObject, exec->emptyList())); ASSERT(isJSArray(thisValue)); - JSArray* thisObj = asArray(thisValue); - - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); + JSArray* thisArray = asArray(thisValue); + + unsigned length = thisArray->length(); - StringRecursionChecker checker(exec, thisObj); + StringRecursionChecker checker(exec, thisArray); if (JSValue earlyReturnValue = checker.earlyReturnValue()) return JSValue::encode(earlyReturnValue); - String separator(",", String::ConstructFromLiteral); - JSStringJoiner stringJoiner(separator, length); - for (unsigned k = 0; k < length; k++) { - JSValue element; - if (thisObj->canGetIndexQuickly(k)) - element = thisObj->getIndexQuickly(k); - else { - element = thisObj->get(exec, k); + JSStringJoiner joiner(*exec, ',', length); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + + for (unsigned i = 0; i < length; ++i) { + JSValue element = thisArray->tryGetIndexQuickly(i); + if (!element) { + element = thisArray->get(exec, i); if (exec->hadException()) return JSValue::encode(jsUndefined()); } - - if (element.isUndefinedOrNull()) - stringJoiner.append(String()); - else - stringJoiner.append(element.toWTFString(exec)); - + joiner.append(*exec, element); if (exec->hadException()) return JSValue::encode(jsUndefined()); } - return JSValue::encode(stringJoiner.join(exec)); + + return JSValue::encode(joiner.join(*exec)); } EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec) { - JSValue thisValue = exec->hostThisValue(); + JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); - if (!thisValue.inherits(&JSArray::s_info)) - return throwVMTypeError(exec); - JSObject* thisObj = asArray(thisValue); + JSObject* thisObject = thisValue.toObject(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + unsigned length = getLength(exec, thisObject); if (exec->hadException()) return JSValue::encode(jsUndefined()); - StringRecursionChecker checker(exec, thisObj); + StringRecursionChecker checker(exec, thisObject); if (JSValue earlyReturnValue = checker.earlyReturnValue()) return JSValue::encode(earlyReturnValue); - String separator(",", String::ConstructFromLiteral); - JSStringJoiner stringJoiner(separator, length); - for (unsigned k = 0; k < length; k++) { - JSValue element = thisObj->get(exec, k); + JSStringJoiner stringJoiner(*exec, ',', length); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + +#if ENABLE(INTL) + ArgList arguments(exec); + for (unsigned i = 0; i < length; ++i) { + JSValue element = thisObject->getIndex(exec, i); if (exec->hadException()) return JSValue::encode(jsUndefined()); - if (!element.isUndefinedOrNull()) { - JSObject* o = element.toObject(exec); - JSValue conversionFunction = o->get(exec, exec->propertyNames().toLocaleString); + if (element.isUndefinedOrNull()) + element = jsEmptyString(exec); + else { + JSValue conversionFunction = element.get(exec, exec->propertyNames().toLocaleString); if (exec->hadException()) return JSValue::encode(jsUndefined()); - String str; CallData callData; CallType callType = getCallData(conversionFunction, callData); - if (callType != CallTypeNone) - str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toWTFString(exec); - else - str = element.toWTFString(exec); + if (callType != CallTypeNone) { + element = call(exec, conversionFunction, callType, callData, element, arguments); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + } + } + stringJoiner.append(*exec, element); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + } +#else // !ENABLE(INTL) + for (unsigned i = 0; i < length; ++i) { + JSValue element = thisObject->getIndex(exec, i); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + if (element.isUndefinedOrNull()) + continue; + JSValue conversionFunction = element.get(exec, exec->propertyNames().toLocaleString); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + CallData callData; + CallType callType = getCallData(conversionFunction, callData); + if (callType != CallTypeNone) { + element = call(exec, conversionFunction, callType, callData, element, exec->emptyList()); if (exec->hadException()) return JSValue::encode(jsUndefined()); - stringJoiner.append(str); } + stringJoiner.append(*exec, element); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); } +#endif // !ENABLE(INTL) - return JSValue::encode(stringJoiner.join(exec)); + return JSValue::encode(stringJoiner.join(*exec)); } -EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) +static inline bool isHole(double value) { - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - StringRecursionChecker checker(exec, thisObj); - if (JSValue earlyReturnValue = checker.earlyReturnValue()) - return JSValue::encode(earlyReturnValue); - - String separator; - if (!exec->argument(0).isUndefined()) - separator = exec->argument(0).toWTFString(exec); - if (separator.isNull()) - separator = String(",", String::ConstructFromLiteral); + return std::isnan(value); +} - JSStringJoiner stringJoiner(separator, length); +static inline bool isHole(const WriteBarrier& value) +{ + return !value; +} - unsigned k = 0; - if (isJSArray(thisObj)) { - JSArray* array = asArray(thisObj); +template static inline bool containsHole(T* data, unsigned length) +{ + for (unsigned i = 0; i < length; ++i) { + if (isHole(data[i])) + return true; + } + return false; +} - for (; k < length; k++) { - if (!array->canGetIndexQuickly(k)) - break; +static inline bool holesMustForwardToPrototype(ExecState& state, JSObject* object) +{ + auto& vm = state.vm(); + return object->structure(vm)->holesMustForwardToPrototype(vm); +} - JSValue element = array->getIndexQuickly(k); - if (!element.isUndefinedOrNull()) - stringJoiner.append(element.toWTFStringInline(exec)); - else - stringJoiner.append(String()); +static inline JSValue join(ExecState& state, JSObject* thisObject, StringView separator) +{ + unsigned length = getLength(&state, thisObject); + if (state.hadException()) + return jsUndefined(); + + switch (thisObject->indexingType()) { + case ALL_CONTIGUOUS_INDEXING_TYPES: + case ALL_INT32_INDEXING_TYPES: { + auto& butterfly = *thisObject->butterfly(); + if (length > butterfly.publicLength()) + break; + JSStringJoiner joiner(state, separator, length); + if (state.hadException()) + return jsUndefined(); + auto data = butterfly.contiguous().data(); + bool holesKnownToBeOK = false; + for (unsigned i = 0; i < length; ++i) { + if (JSValue value = data[i].get()) { + if (!joiner.appendWithoutSideEffects(state, value)) + goto generalCase; + } else { + if (!holesKnownToBeOK) { + if (holesMustForwardToPrototype(state, thisObject)) + goto generalCase; + holesKnownToBeOK = true; + } + joiner.appendEmptyString(); + } } + return joiner.join(state); + } + case ALL_DOUBLE_INDEXING_TYPES: { + auto& butterfly = *thisObject->butterfly(); + if (length > butterfly.publicLength()) + break; + JSStringJoiner joiner(state, separator, length); + if (state.hadException()) + return jsUndefined(); + auto data = butterfly.contiguousDouble().data(); + bool holesKnownToBeOK = false; + for (unsigned i = 0; i < length; ++i) { + double value = data[i]; + if (!isHole(value)) + joiner.append(state, jsDoubleNumber(value)); + else { + if (!holesKnownToBeOK) { + if (thisObject->structure(state.vm())->holesMustForwardToPrototype(state.vm())) + goto generalCase; + holesKnownToBeOK = true; + } + joiner.appendEmptyString(); + } + } + return joiner.join(state); + } + case ALL_ARRAY_STORAGE_INDEXING_TYPES: { + auto& storage = *thisObject->butterfly()->arrayStorage(); + if (length > storage.vectorLength()) + break; + if (storage.hasHoles() && thisObject->structure(state.vm())->holesMustForwardToPrototype(state.vm())) + break; + JSStringJoiner joiner(state, separator, length); + if (state.hadException()) + return jsUndefined(); + auto data = storage.vector().data(); + for (unsigned i = 0; i < length; ++i) { + if (JSValue value = data[i].get()) { + if (!joiner.appendWithoutSideEffects(state, value)) + goto generalCase; + } else + joiner.appendEmptyString(); + } + return joiner.join(state); + } } - for (; k < length; k++) { - JSValue element = thisObj->get(exec, k); - if (!element.isUndefinedOrNull()) - stringJoiner.append(element.toWTFStringInline(exec)); - else - stringJoiner.append(String()); +generalCase: + JSStringJoiner joiner(state, separator, length); + if (state.hadException()) + return jsUndefined(); + for (unsigned i = 0; i < length; ++i) { + JSValue element = thisObject->getIndex(&state, i); + if (state.hadException()) + return jsUndefined(); + joiner.append(state, element); + if (state.hadException()) + return jsUndefined(); } + return joiner.join(state); +} + +EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) +{ + JSObject* thisObject = exec->thisValue().toThis(exec, StrictMode).toObject(exec); - return JSValue::encode(stringJoiner.join(exec)); + StringRecursionChecker checker(exec, thisObject); + if (JSValue earlyReturnValue = checker.earlyReturnValue()) + return JSValue::encode(earlyReturnValue); + + JSValue separatorValue = exec->argument(0); + if (separatorValue.isUndefined()) { + const LChar comma = ','; + return JSValue::encode(join(*exec, thisObject, { &comma, 1 })); + } + + JSString* separator = separatorValue.toString(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + return JSValue::encode(join(*exec, thisObject, separator->view(exec).get())); } EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec) { - JSValue thisValue = exec->hostThisValue(); - JSArray* arr = constructEmptyArray(exec, 0); - unsigned n = 0; + JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); + unsigned argCount = exec->argumentCount(); JSValue curArg = thisValue.toObject(exec); - if (exec->hadException()) + Checked finalArraySize = 0; + + // We need to do species construction before geting the rest of the elements. + std::pair speciesResult = speciesConstructArray(exec, curArg.getObject(), 0); + if (speciesResult.first == SpeciesConstructResult::Exception) return JSValue::encode(jsUndefined()); - size_t i = 0; - size_t argCount = exec->argumentCount(); - while (1) { - if (curArg.inherits(&JSArray::s_info)) { - unsigned length = curArg.get(exec, exec->propertyNames().length).toUInt32(exec); - JSObject* curObject = curArg.toObject(exec); + + JSArray* currentArray = nullptr; + JSArray* previousArray = nullptr; + for (unsigned i = 0; ; ++i) { + previousArray = currentArray; + currentArray = jsDynamicCast(curArg); + if (currentArray) { + // Can't use JSArray::length here because this might be a RuntimeArray! + finalArraySize += getLength(exec, currentArray); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + } else + ++finalArraySize; + if (i == argCount) + break; + curArg = exec->uncheckedArgument(i); + } + + if (finalArraySize.hasOverflowed()) + return JSValue::encode(throwOutOfMemoryError(exec)); + + if (speciesResult.first == SpeciesConstructResult::FastPath && argCount == 1 && previousArray && currentArray && finalArraySize.unsafeGet() < MIN_SPARSE_ARRAY_INDEX) { + IndexingType type = JSArray::fastConcatType(exec->vm(), *previousArray, *currentArray); + if (type != NonArray) + return previousArray->fastConcatWith(*exec, *currentArray); + } + + ASSERT(speciesResult.first != SpeciesConstructResult::Exception); + + JSObject* result; + if (speciesResult.first == SpeciesConstructResult::CreatedObject) + result = speciesResult.second; + else { + // We add the newTarget because the compiler gets confused between 0 being a number and a pointer. + result = constructEmptyArray(exec, nullptr, 0, JSValue()); + } + + curArg = thisValue.toObject(exec); + unsigned n = 0; + for (unsigned i = 0; ; ++i) { + if (JSArray* currentArray = jsDynamicCast(curArg)) { + // Can't use JSArray::length here because this might be a RuntimeArray! + unsigned length = getLength(exec, currentArray); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); for (unsigned k = 0; k < length; ++k) { - JSValue v = getProperty(exec, curObject, k); + JSValue v = getProperty(exec, currentArray, k); if (exec->hadException()) return JSValue::encode(jsUndefined()); if (v) - arr->putDirectIndex(exec, n, v); + result->putDirectIndex(exec, n, v); n++; } } else { - arr->putDirectIndex(exec, n, curArg); + result->putDirectIndex(exec, n, curArg); n++; } if (i == argCount) break; - curArg = (exec->argument(i)); - ++i; + curArg = exec->uncheckedArgument(i); } - arr->setLength(exec, n); - return JSValue::encode(arr); + setLength(exec, result, n); + return JSValue::encode(result); } EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec) { - JSValue thisValue = exec->hostThisValue(); + JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); if (isJSArray(thisValue)) return JSValue::encode(asArray(thisValue)->pop(exec)); JSObject* thisObj = thisValue.toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + unsigned length = getLength(exec, thisObj); if (exec->hadException()) return JSValue::encode(jsUndefined()); JSValue result; if (length == 0) { - putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length)); + putLength(exec, thisObj, jsNumber(length)); result = jsUndefined(); } else { result = thisObj->get(exec, length - 1); if (exec->hadException()) return JSValue::encode(jsUndefined()); - if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, length - 1)) { + if (!thisObj->methodTable(exec->vm())->deletePropertyByIndex(thisObj, exec, length - 1)) { throwTypeError(exec, ASCIILiteral("Unable to delete property.")); return JSValue::encode(jsUndefined()); } - putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1)); + putLength(exec, thisObj, jsNumber(length - 1)); } return JSValue::encode(result); } EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec) { - JSValue thisValue = exec->hostThisValue(); + JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); if (isJSArray(thisValue) && exec->argumentCount() == 1) { JSArray* array = asArray(thisValue); - array->push(exec, exec->argument(0)); + array->push(exec, exec->uncheckedArgument(0)); return JSValue::encode(jsNumber(array->length())); } JSObject* thisObj = thisValue.toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + unsigned length = getLength(exec, thisObj); if (exec->hadException()) return JSValue::encode(jsUndefined()); for (unsigned n = 0; n < exec->argumentCount(); n++) { // Check for integer overflow; where safe we can do a fast put by index. if (length + n >= length) - thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->argument(n), true); + thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->uncheckedArgument(n), true); else { - PutPropertySlot slot; - Identifier propertyName(exec, JSValue(static_cast(length) + static_cast(n)).toWTFString(exec)); - thisObj->methodTable()->put(thisObj, exec, propertyName, exec->argument(n), slot); + PutPropertySlot slot(thisObj); + Identifier propertyName = Identifier::fromString(exec, JSValue(static_cast(length) + static_cast(n)).toWTFString(exec)); + thisObj->methodTable()->put(thisObj, exec, propertyName, exec->uncheckedArgument(n), slot); } if (exec->hadException()) return JSValue::encode(jsUndefined()); } JSValue newLength(static_cast(length) + static_cast(exec->argumentCount())); - putProperty(exec, thisObj, exec->propertyNames().length, newLength); + putLength(exec, thisObj, newLength); return JSValue::encode(newLength); } EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec) { - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + JSObject* thisObject = exec->thisValue().toThis(exec, StrictMode).toObject(exec); + + unsigned length = getLength(exec, thisObject); if (exec->hadException()) return JSValue::encode(jsUndefined()); + switch (thisObject->indexingType()) { + case ALL_CONTIGUOUS_INDEXING_TYPES: + case ALL_INT32_INDEXING_TYPES: { + auto& butterfly = *thisObject->butterfly(); + if (length > butterfly.publicLength()) + break; + auto data = butterfly.contiguous().data(); + if (containsHole(data, length) && holesMustForwardToPrototype(*exec, thisObject)) + break; + std::reverse(data, data + length); + return JSValue::encode(thisObject); + } + case ALL_DOUBLE_INDEXING_TYPES: { + auto& butterfly = *thisObject->butterfly(); + if (length > butterfly.publicLength()) + break; + auto data = butterfly.contiguousDouble().data(); + if (containsHole(data, length) && holesMustForwardToPrototype(*exec, thisObject)) + break; + std::reverse(data, data + length); + return JSValue::encode(thisObject); + } + case ALL_ARRAY_STORAGE_INDEXING_TYPES: { + auto& storage = *thisObject->butterfly()->arrayStorage(); + if (length > storage.vectorLength()) + break; + if (storage.hasHoles() && holesMustForwardToPrototype(*exec, thisObject)) + break; + auto data = storage.vector().data(); + std::reverse(data, data + length); + return JSValue::encode(thisObject); + } + } + unsigned middle = length / 2; for (unsigned k = 0; k < middle; k++) { unsigned lk1 = length - k - 1; - JSValue obj2 = getProperty(exec, thisObj, lk1); + JSValue obj2 = getProperty(exec, thisObject, lk1); if (exec->hadException()) return JSValue::encode(jsUndefined()); - JSValue obj = getProperty(exec, thisObj, k); + JSValue obj = getProperty(exec, thisObject, k); if (exec->hadException()) return JSValue::encode(jsUndefined()); if (obj2) { - thisObj->methodTable()->putByIndex(thisObj, exec, k, obj2, true); + thisObject->putByIndexInline(exec, k, obj2, true); if (exec->hadException()) return JSValue::encode(jsUndefined()); - } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k)) { + } else if (!thisObject->methodTable(exec->vm())->deletePropertyByIndex(thisObject, exec, k)) { throwTypeError(exec, ASCIILiteral("Unable to delete property.")); return JSValue::encode(jsUndefined()); } if (obj) { - thisObj->methodTable()->putByIndex(thisObj, exec, lk1, obj, true); + thisObject->putByIndexInline(exec, lk1, obj, true); if (exec->hadException()) return JSValue::encode(jsUndefined()); - } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, lk1)) { + } else if (!thisObject->methodTable(exec->vm())->deletePropertyByIndex(thisObject, exec, lk1)) { throwTypeError(exec, ASCIILiteral("Unable to delete property.")); return JSValue::encode(jsUndefined()); } } - return JSValue::encode(thisObj); + return JSValue::encode(thisObject); } EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec) { - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); + unsigned length = getLength(exec, thisObj); if (exec->hadException()) return JSValue::encode(jsUndefined()); JSValue result; if (length == 0) { - putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length)); + putLength(exec, thisObj, jsNumber(length)); result = jsUndefined(); } else { - result = thisObj->get(exec, 0); + result = thisObj->getIndex(exec, 0); shift(exec, thisObj, 0, 1, 0, length); if (exec->hadException()) return JSValue::encode(jsUndefined()); - putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1)); + putLength(exec, thisObj, jsNumber(length - 1)); } return JSValue::encode(result); } @@ -575,204 +819,73 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec) { // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10 - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); + unsigned length = getLength(exec, thisObj); if (exec->hadException()) return JSValue::encode(jsUndefined()); - // We return a new array - JSArray* resObj = constructEmptyArray(exec, 0); - JSValue result = resObj; - unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length); unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length); + std::pair speciesResult = speciesConstructArray(exec, thisObj, end - begin); + // We can only get an exception if we call some user function. + if (UNLIKELY(speciesResult.first == SpeciesConstructResult::Exception)) + return JSValue::encode(jsUndefined()); + + if (LIKELY(speciesResult.first == SpeciesConstructResult::FastPath && isJSArray(thisObj))) { + if (JSArray* result = asArray(thisObj)->fastSlice(*exec, begin, end - begin)) + return JSValue::encode(result); + } + + JSObject* result; + if (speciesResult.first == SpeciesConstructResult::CreatedObject) + result = speciesResult.second; + else + result = constructEmptyArray(exec, nullptr, end - begin); + unsigned n = 0; for (unsigned k = begin; k < end; k++, n++) { JSValue v = getProperty(exec, thisObj, k); if (exec->hadException()) return JSValue::encode(jsUndefined()); if (v) - resObj->putDirectIndex(exec, n, v); + result->putDirectIndex(exec, n, v); } - resObj->setLength(exec, n); + setLength(exec, result, n); return JSValue::encode(result); } -inline JSValue getOrHole(JSObject* obj, ExecState* exec, unsigned propertyName) -{ - PropertySlot slot(obj); - if (obj->getPropertySlot(exec, propertyName, slot)) - return slot.getValue(exec, propertyName); - - return JSValue(); -} - -static bool attemptFastSort(ExecState* exec, JSObject* thisObj, JSValue function, CallData& callData, CallType& callType) -{ - if (thisObj->classInfo() != &JSArray::s_info - || asArray(thisObj)->hasSparseMap() - || shouldUseSlowPut(thisObj->structure()->indexingType())) - return false; - - if (isNumericCompareFunction(exec, callType, callData)) - asArray(thisObj)->sortNumeric(exec, function, callType, callData); - else if (callType != CallTypeNone) - asArray(thisObj)->sort(exec, function, callType, callData); - else - asArray(thisObj)->sort(exec); - return true; -} - -static bool performSlowSort(ExecState* exec, JSObject* thisObj, unsigned length, JSValue function, CallData& callData, CallType& callType) -{ - // "Min" sort. Not the fastest, but definitely less code than heapsort - // or quicksort, and much less swapping than bubblesort/insertionsort. - for (unsigned i = 0; i < length - 1; ++i) { - JSValue iObj = getOrHole(thisObj, exec, i); - if (exec->hadException()) - return false; - unsigned themin = i; - JSValue minObj = iObj; - for (unsigned j = i + 1; j < length; ++j) { - JSValue jObj = getOrHole(thisObj, exec, j); - if (exec->hadException()) - return false; - double compareResult; - if (!jObj) - compareResult = 1; - else if (!minObj) - compareResult = -1; - else if (jObj.isUndefined()) - compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1) - else if (minObj.isUndefined()) - compareResult = -1; - else if (callType != CallTypeNone) { - MarkedArgumentBuffer l; - l.append(jObj); - l.append(minObj); - compareResult = call(exec, function, callType, callData, jsUndefined(), l).toNumber(exec); - } else - compareResult = codePointCompareLessThan(jObj.toWTFStringInline(exec), minObj.toWTFStringInline(exec)) ? -1 : 1; - - if (compareResult < 0) { - themin = j; - minObj = jObj; - } - } - // Swap themin and i - if (themin > i) { - if (minObj) { - thisObj->methodTable()->putByIndex(thisObj, exec, i, minObj, true); - if (exec->hadException()) - return false; - } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, i)) { - throwTypeError(exec, "Unable to delete property."); - return false; - } - if (iObj) { - thisObj->methodTable()->putByIndex(thisObj, exec, themin, iObj, true); - if (exec->hadException()) - return false; - } else if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, themin)) { - throwTypeError(exec, "Unable to delete property."); - return false; - } - } - } - return true; -} - -EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) +EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) { - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - if (!length || exec->hadException()) - return JSValue::encode(thisObj); + // 15.4.4.12 - JSValue function = exec->argument(0); - CallData callData; - CallType callType = getCallData(function, callData); + VM& vm = exec->vm(); - if (attemptFastSort(exec, thisObj, function, callData, callType)) - return JSValue::encode(thisObj); - - // Assume that for small-ish arrays, doing the slow sort directly is better. - if (length < 1000) - return performSlowSort(exec, thisObj, length, function, callData, callType) ? JSValue::encode(thisObj) : JSValue::encode(jsUndefined()); - - JSGlobalObject* globalObject = JSGlobalObject::create( - exec->vm(), JSGlobalObject::createStructure(exec->vm(), jsNull())); - JSArray* flatArray = constructEmptyArray(globalObject->globalExec(), 0); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - PropertyNameArray nameArray(exec); - thisObj->methodTable()->getPropertyNames(thisObj, exec, nameArray, IncludeDontEnumProperties); + JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); + unsigned length = getLength(exec, thisObj); if (exec->hadException()) return JSValue::encode(jsUndefined()); - Vector keys; - for (size_t i = 0; i < nameArray.size(); ++i) { - PropertyName name = nameArray[i]; - uint32_t index = name.asIndex(); - if (index == PropertyName::NotAnIndex) - continue; - - JSValue value = getOrHole(thisObj, exec, index); - if (exec->hadException()) + if (!exec->argumentCount()) { + std::pair speciesResult = speciesConstructArray(exec, thisObj, 0); + if (speciesResult.first == SpeciesConstructResult::Exception) return JSValue::encode(jsUndefined()); - if (!value) - continue; - keys.append(index); - flatArray->push(exec, value); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - } - - if (!attemptFastSort(exec, flatArray, function, callData, callType) - && !performSlowSort(exec, flatArray, flatArray->length(), function, callData, callType)) - return JSValue::encode(jsUndefined()); - - for (size_t i = 0; i < keys.size(); ++i) { - size_t index = keys[i]; - if (index < flatArray->length()) - continue; - - if (!thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, index)) { - throwTypeError(exec, "Unable to delete property."); - return JSValue::encode(jsUndefined()); - } - } - - for (size_t i = flatArray->length(); i--;) { - JSValue value = getOrHole(flatArray, exec, i); - RELEASE_ASSERT(value); - thisObj->methodTable()->putByIndex(thisObj, exec, i, value, true); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - } - - return JSValue::encode(thisObj); -} -EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) -{ - // 15.4.4.12 + JSObject* result; + if (speciesResult.first == SpeciesConstructResult::CreatedObject) + result = speciesResult.second; + else + result = constructEmptyArray(exec, nullptr); - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - if (!exec->argumentCount()) - return JSValue::encode(constructEmptyArray(exec, 0)); + setLength(exec, result, 0); + return JSValue::encode(result); + } unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length); unsigned deleteCount = length - begin; if (exec->argumentCount() > 1) { - double deleteDouble = exec->argument(1).toInteger(exec); + double deleteDouble = exec->uncheckedArgument(1).toInteger(exec); if (deleteDouble < 0) deleteCount = 0; else if (deleteDouble > length - begin) @@ -781,17 +894,38 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) deleteCount = static_cast(deleteDouble); } - JSArray* resObj = JSArray::tryCreateUninitialized(exec->vm(), exec->lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), deleteCount); - if (!resObj) - return JSValue::encode(throwOutOfMemoryError(exec)); + std::pair speciesResult = speciesConstructArray(exec, thisObj, deleteCount); + if (speciesResult.first == SpeciesConstructResult::Exception) + return JSValue::encode(jsUndefined()); - JSValue result = resObj; - VM& vm = exec->vm(); - for (unsigned k = 0; k < deleteCount; k++) { - JSValue v = getProperty(exec, thisObj, k + begin); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - resObj->initializeIndex(vm, k, v); + JSObject* result = nullptr; + if (speciesResult.first == SpeciesConstructResult::FastPath && isJSArray(thisObj)) + result = asArray(thisObj)->fastSlice(*exec, begin, deleteCount); + + if (!result) { + if (speciesResult.first == SpeciesConstructResult::CreatedObject) { + result = speciesResult.second; + + for (unsigned k = 0; k < deleteCount; ++k) { + JSValue v = getProperty(exec, thisObj, k + begin); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + result->putByIndexInline(exec, k, v, true); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + } + } else { + result = JSArray::tryCreateUninitialized(vm, exec->lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), deleteCount); + if (!result) + return JSValue::encode(throwOutOfMemoryError(exec)); + + for (unsigned k = 0; k < deleteCount; ++k) { + JSValue v = getProperty(exec, thisObj, k + begin); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + result->initializeIndex(vm, k, v); + } + } } unsigned additionalArgs = std::max(exec->argumentCount() - 2, 0); @@ -805,12 +939,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) return JSValue::encode(jsUndefined()); } for (unsigned k = 0; k < additionalArgs; ++k) { - thisObj->methodTable()->putByIndex(thisObj, exec, k + begin, exec->argument(k + 2), true); + thisObj->putByIndexInline(exec, k + begin, exec->uncheckedArgument(k + 2), true); if (exec->hadException()) return JSValue::encode(jsUndefined()); } - putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - deleteCount + additionalArgs)); + setLength(exec, thisObj, length - deleteCount + additionalArgs); return JSValue::encode(result); } @@ -818,8 +952,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec) { // 15.4.4.13 - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); + unsigned length = getLength(exec, thisObj); if (exec->hadException()) return JSValue::encode(jsUndefined()); @@ -830,459 +964,20 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec) return JSValue::encode(jsUndefined()); } for (unsigned k = 0; k < nrArgs; ++k) { - thisObj->methodTable()->putByIndex(thisObj, exec, k, exec->argument(k), true); + thisObj->putByIndexInline(exec, k, exec->uncheckedArgument(k), true); if (exec->hadException()) return JSValue::encode(jsUndefined()); } JSValue result = jsNumber(length + nrArgs); - putProperty(exec, thisObj, exec->propertyNames().length, result); - return JSValue::encode(result); -} - -EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) -{ - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - JSValue function = exec->argument(0); - CallData callData; - CallType callType = getCallData(function, callData); - if (callType == CallTypeNone) - return throwVMTypeError(exec); - - JSValue applyThis = exec->argument(1); - JSArray* resultArray = constructEmptyArray(exec, 0); - - unsigned filterIndex = 0; - unsigned k = 0; - if (callType == CallTypeJS && isJSArray(thisObj)) { - JSFunction* f = jsCast(function); - JSArray* array = asArray(thisObj); - CachedCall cachedCall(exec, f, 3); - for (; k < length && !exec->hadException(); ++k) { - if (!array->canGetIndexQuickly(k)) - break; - JSValue v = array->getIndexQuickly(k); - cachedCall.setThis(applyThis); - cachedCall.setArgument(0, v); - cachedCall.setArgument(1, jsNumber(k)); - cachedCall.setArgument(2, thisObj); - - JSValue result = cachedCall.call(); - if (result.toBoolean(exec)) - resultArray->putDirectIndex(exec, filterIndex++, v); - } - if (k == length) - return JSValue::encode(resultArray); - } - for (; k < length && !exec->hadException(); ++k) { - PropertySlot slot(thisObj); - if (!thisObj->getPropertySlot(exec, k, slot)) - continue; - JSValue v = slot.getValue(exec, k); - - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - MarkedArgumentBuffer eachArguments; - eachArguments.append(v); - eachArguments.append(jsNumber(k)); - eachArguments.append(thisObj); - - JSValue result = call(exec, function, callType, callData, applyThis, eachArguments); - if (result.toBoolean(exec)) - resultArray->putDirectIndex(exec, filterIndex++, v); - } - return JSValue::encode(resultArray); -} - -EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec) -{ - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - JSValue function = exec->argument(0); - CallData callData; - CallType callType = getCallData(function, callData); - if (callType == CallTypeNone) - return throwVMTypeError(exec); - - JSValue applyThis = exec->argument(1); - - JSArray* resultArray = constructEmptyArray(exec, 0, length); - unsigned k = 0; - if (callType == CallTypeJS && isJSArray(thisObj)) { - JSFunction* f = jsCast(function); - JSArray* array = asArray(thisObj); - CachedCall cachedCall(exec, f, 3); - for (; k < length && !exec->hadException(); ++k) { - if (UNLIKELY(!array->canGetIndexQuickly(k))) - break; - - cachedCall.setThis(applyThis); - cachedCall.setArgument(0, array->getIndexQuickly(k)); - cachedCall.setArgument(1, jsNumber(k)); - cachedCall.setArgument(2, thisObj); - - resultArray->putDirectIndex(exec, k, cachedCall.call()); - } - } - for (; k < length && !exec->hadException(); ++k) { - PropertySlot slot(thisObj); - if (!thisObj->getPropertySlot(exec, k, slot)) - continue; - JSValue v = slot.getValue(exec, k); - - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - MarkedArgumentBuffer eachArguments; - eachArguments.append(v); - eachArguments.append(jsNumber(k)); - eachArguments.append(thisObj); - - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - JSValue result = call(exec, function, callType, callData, applyThis, eachArguments); - resultArray->putDirectIndex(exec, k, result); - } - - return JSValue::encode(resultArray); -} - -// Documentation for these three is available at: -// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:every -// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach -// http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some - -EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec) -{ - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - JSValue function = exec->argument(0); - CallData callData; - CallType callType = getCallData(function, callData); - if (callType == CallTypeNone) - return throwVMTypeError(exec); - - JSValue applyThis = exec->argument(1); - - JSValue result = jsBoolean(true); - - unsigned k = 0; - if (callType == CallTypeJS && isJSArray(thisObj)) { - JSFunction* f = jsCast(function); - JSArray* array = asArray(thisObj); - CachedCall cachedCall(exec, f, 3); - for (; k < length && !exec->hadException(); ++k) { - if (UNLIKELY(!array->canGetIndexQuickly(k))) - break; - - cachedCall.setThis(applyThis); - cachedCall.setArgument(0, array->getIndexQuickly(k)); - cachedCall.setArgument(1, jsNumber(k)); - cachedCall.setArgument(2, thisObj); - JSValue result = cachedCall.call(); - if (!result.toBoolean(exec)) - return JSValue::encode(jsBoolean(false)); - } - } - for (; k < length && !exec->hadException(); ++k) { - PropertySlot slot(thisObj); - if (!thisObj->getPropertySlot(exec, k, slot)) - continue; - - MarkedArgumentBuffer eachArguments; - eachArguments.append(slot.getValue(exec, k)); - eachArguments.append(jsNumber(k)); - eachArguments.append(thisObj); - - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); - if (!predicateResult) { - result = jsBoolean(false); - break; - } - } - - return JSValue::encode(result); -} - -EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec) -{ - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - JSValue function = exec->argument(0); - CallData callData; - CallType callType = getCallData(function, callData); - if (callType == CallTypeNone) - return throwVMTypeError(exec); - - JSValue applyThis = exec->argument(1); - - unsigned k = 0; - if (callType == CallTypeJS && isJSArray(thisObj)) { - JSFunction* f = jsCast(function); - JSArray* array = asArray(thisObj); - CachedCall cachedCall(exec, f, 3); - for (; k < length && !exec->hadException(); ++k) { - if (UNLIKELY(!array->canGetIndexQuickly(k))) - break; - - cachedCall.setThis(applyThis); - cachedCall.setArgument(0, array->getIndexQuickly(k)); - cachedCall.setArgument(1, jsNumber(k)); - cachedCall.setArgument(2, thisObj); - - cachedCall.call(); - } - } - for (; k < length && !exec->hadException(); ++k) { - PropertySlot slot(thisObj); - if (!thisObj->getPropertySlot(exec, k, slot)) - continue; - - MarkedArgumentBuffer eachArguments; - eachArguments.append(slot.getValue(exec, k)); - eachArguments.append(jsNumber(k)); - eachArguments.append(thisObj); - - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - call(exec, function, callType, callData, applyThis, eachArguments); - } - return JSValue::encode(jsUndefined()); -} - -EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec) -{ - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - JSValue function = exec->argument(0); - CallData callData; - CallType callType = getCallData(function, callData); - if (callType == CallTypeNone) - return throwVMTypeError(exec); - - JSValue applyThis = exec->argument(1); - - JSValue result = jsBoolean(false); - - unsigned k = 0; - if (callType == CallTypeJS && isJSArray(thisObj)) { - JSFunction* f = jsCast(function); - JSArray* array = asArray(thisObj); - CachedCall cachedCall(exec, f, 3); - for (; k < length && !exec->hadException(); ++k) { - if (UNLIKELY(!array->canGetIndexQuickly(k))) - break; - - cachedCall.setThis(applyThis); - cachedCall.setArgument(0, array->getIndexQuickly(k)); - cachedCall.setArgument(1, jsNumber(k)); - cachedCall.setArgument(2, thisObj); - JSValue result = cachedCall.call(); - if (result.toBoolean(exec)) - return JSValue::encode(jsBoolean(true)); - } - } - for (; k < length && !exec->hadException(); ++k) { - PropertySlot slot(thisObj); - if (!thisObj->getPropertySlot(exec, k, slot)) - continue; - - MarkedArgumentBuffer eachArguments; - eachArguments.append(slot.getValue(exec, k)); - eachArguments.append(jsNumber(k)); - eachArguments.append(thisObj); - - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec); - if (predicateResult) { - result = jsBoolean(true); - break; - } - } + putLength(exec, thisObj, result); return JSValue::encode(result); } -EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec) -{ - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - JSValue function = exec->argument(0); - CallData callData; - CallType callType = getCallData(function, callData); - if (callType == CallTypeNone) - return throwVMTypeError(exec); - - unsigned i = 0; - JSValue rv; - if (!length && exec->argumentCount() == 1) - return throwVMTypeError(exec); - - JSArray* array = 0; - if (isJSArray(thisObj)) - array = asArray(thisObj); - - if (exec->argumentCount() >= 2) - rv = exec->argument(1); - else if (array && array->canGetIndexQuickly(0)) { - rv = array->getIndexQuickly(0); - i = 1; - } else { - for (i = 0; i < length; i++) { - rv = getProperty(exec, thisObj, i); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - if (rv) - break; - } - if (!rv) - return throwVMTypeError(exec); - i++; - } - - if (callType == CallTypeJS && array) { - CachedCall cachedCall(exec, jsCast(function), 4); - for (; i < length && !exec->hadException(); ++i) { - cachedCall.setThis(jsUndefined()); - cachedCall.setArgument(0, rv); - JSValue v; - if (LIKELY(array->canGetIndexQuickly(i))) - v = array->getIndexQuickly(i); - else - break; // length has been made unsafe while we enumerate fallback to slow path - cachedCall.setArgument(1, v); - cachedCall.setArgument(2, jsNumber(i)); - cachedCall.setArgument(3, array); - rv = cachedCall.call(); - } - if (i == length) // only return if we reached the end of the array - return JSValue::encode(rv); - } - - for (; i < length && !exec->hadException(); ++i) { - JSValue prop = getProperty(exec, thisObj, i); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - if (!prop) - continue; - - MarkedArgumentBuffer eachArguments; - eachArguments.append(rv); - eachArguments.append(prop); - eachArguments.append(jsNumber(i)); - eachArguments.append(thisObj); - - rv = call(exec, function, callType, callData, jsUndefined(), eachArguments); - } - return JSValue::encode(rv); -} - -EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec) -{ - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - - JSValue function = exec->argument(0); - CallData callData; - CallType callType = getCallData(function, callData); - if (callType == CallTypeNone) - return throwVMTypeError(exec); - - unsigned i = 0; - JSValue rv; - if (!length && exec->argumentCount() == 1) - return throwVMTypeError(exec); - - JSArray* array = 0; - if (isJSArray(thisObj)) - array = asArray(thisObj); - - if (exec->argumentCount() >= 2) - rv = exec->argument(1); - else if (array && array->canGetIndexQuickly(length - 1)) { - rv = array->getIndexQuickly(length - 1); - i = 1; - } else { - for (i = 0; i < length; i++) { - rv = getProperty(exec, thisObj, length - i - 1); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - if (rv) - break; - } - if (!rv) - return throwVMTypeError(exec); - i++; - } - - if (callType == CallTypeJS && array) { - CachedCall cachedCall(exec, jsCast(function), 4); - for (; i < length && !exec->hadException(); ++i) { - unsigned idx = length - i - 1; - cachedCall.setThis(jsUndefined()); - cachedCall.setArgument(0, rv); - if (UNLIKELY(!array->canGetIndexQuickly(idx))) - break; // length has been made unsafe while we enumerate fallback to slow path - cachedCall.setArgument(1, array->getIndexQuickly(idx)); - cachedCall.setArgument(2, jsNumber(idx)); - cachedCall.setArgument(3, array); - rv = cachedCall.call(); - } - if (i == length) // only return if we reached the end of the array - return JSValue::encode(rv); - } - - for (; i < length && !exec->hadException(); ++i) { - unsigned idx = length - i - 1; - JSValue prop = getProperty(exec, thisObj, idx); - if (exec->hadException()) - return JSValue::encode(jsUndefined()); - if (!prop) - continue; - - MarkedArgumentBuffer eachArguments; - eachArguments.append(rv); - eachArguments.append(prop); - eachArguments.append(jsNumber(idx)); - eachArguments.append(thisObj); - - rv = call(exec, function, callType, callData, jsUndefined(), eachArguments); - } - return JSValue::encode(rv); -} - EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec) { // 15.4.4.14 - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); + unsigned length = getLength(exec, thisObj); if (exec->hadException()) return JSValue::encode(jsUndefined()); @@ -1304,14 +999,14 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec) { // 15.4.4.15 - JSObject* thisObj = exec->hostThisValue().toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); + unsigned length = getLength(exec, thisObj); if (!length) return JSValue::encode(jsNumber(-1)); unsigned index = length - 1; if (exec->argumentCount() >= 2) { - JSValue fromValue = exec->argument(1); + JSValue fromValue = exec->uncheckedArgument(1); double fromDouble = fromValue.toInteger(exec); if (fromDouble < 0) { fromDouble += length; @@ -1337,4 +1032,79 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec) return JSValue::encode(jsNumber(-1)); } +EncodedJSValue JSC_HOST_CALL arrayProtoFuncValues(ExecState* exec) +{ + JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); + return JSValue::encode(JSArrayIterator::create(exec, exec->callee()->globalObject()->arrayIteratorStructure(), ArrayIterateValue, thisObj)); +} + +EncodedJSValue JSC_HOST_CALL arrayProtoFuncEntries(ExecState* exec) +{ + JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); + return JSValue::encode(JSArrayIterator::create(exec, exec->callee()->globalObject()->arrayIteratorStructure(), ArrayIterateKeyValue, thisObj)); +} + +EncodedJSValue JSC_HOST_CALL arrayProtoFuncKeys(ExecState* exec) +{ + JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); + return JSValue::encode(JSArrayIterator::create(exec, exec->callee()->globalObject()->arrayIteratorStructure(), ArrayIterateKey, thisObj)); +} + +// -------------------- ArrayPrototype.constructor Watchpoint ------------------ + +class ArrayPrototypeAdaptiveInferredPropertyWatchpoint : public AdaptiveInferredPropertyValueWatchpointBase { +public: + typedef AdaptiveInferredPropertyValueWatchpointBase Base; + ArrayPrototypeAdaptiveInferredPropertyWatchpoint(const ObjectPropertyCondition&, ArrayPrototype*); + +private: + virtual void handleFire(const FireDetail&) override; + + ArrayPrototype* m_arrayPrototype; +}; + +void ArrayPrototype::setConstructor(VM& vm, JSObject* constructorProperty, unsigned attributes) +{ + putDirectWithoutTransition(vm, vm.propertyNames->constructor, constructorProperty, attributes); + + // Do the watchpoint on our constructor property + PropertyOffset offset = this->structure()->get(vm, vm.propertyNames->constructor); + ASSERT(isValidOffset(offset)); + this->structure()->startWatchingPropertyForReplacements(vm, offset); + + ObjectPropertyCondition condition = ObjectPropertyCondition::equivalence(vm, this, this, vm.propertyNames->constructor.impl(), constructorProperty); + ASSERT(condition.isWatchable()); + + m_constructorWatchpoint = std::make_unique(condition, this); + m_constructorWatchpoint->install(); + + // Do the watchpoint on the constructor's Symbol.species property + offset = constructorProperty->structure()->get(vm, vm.propertyNames->speciesSymbol); + ASSERT(isValidOffset(offset)); + constructorProperty->structure()->startWatchingPropertyForReplacements(vm, offset); + + ASSERT(constructorProperty->getDirect(offset).isGetterSetter()); + condition = ObjectPropertyCondition::equivalence(vm, this, constructorProperty, vm.propertyNames->speciesSymbol.impl(), constructorProperty->getDirect(offset)); + ASSERT(condition.isWatchable()); + + m_constructorSpeciesWatchpoint = std::make_unique(condition, this); + m_constructorSpeciesWatchpoint->install(); +} + +ArrayPrototypeAdaptiveInferredPropertyWatchpoint::ArrayPrototypeAdaptiveInferredPropertyWatchpoint(const ObjectPropertyCondition& key, ArrayPrototype* prototype) + : Base(key) + , m_arrayPrototype(prototype) +{ +} + +void ArrayPrototypeAdaptiveInferredPropertyWatchpoint::handleFire(const FireDetail& detail) +{ + StringPrintStream out; + out.print("ArrayPrototype adaption of ", key(), " failed: ", detail); + + StringFireDetail stringDetail(out.toCString().data()); + + m_arrayPrototype->m_didChangeConstructorOrSpeciesProperties = true; +} + } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.h b/Source/JavaScriptCore/runtime/ArrayPrototype.h index 37ba6eb7e..64d2163d4 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.h +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2007, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2007, 2011, 2015 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,29 +26,46 @@ namespace JSC { +class ArrayPrototypeAdaptiveInferredPropertyWatchpoint; + class ArrayPrototype : public JSArray { private: - ArrayPrototype(JSGlobalObject*, Structure*); + ArrayPrototype(VM&, Structure*); public: typedef JSArray Base; - static ArrayPrototype* create(ExecState*, JSGlobalObject*, Structure*); + static ArrayPrototype* create(VM&, JSGlobalObject*, Structure*); - static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&); - static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); - - static const ClassInfo s_info; + DECLARE_INFO; static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info, ArrayClass); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass); } + void setConstructor(VM&, JSObject* constructorProperty, unsigned attributes); + + bool didChangeConstructorOrSpeciesProperties() const { return m_didChangeConstructorOrSpeciesProperties; } + + static const bool needsDestruction = false; + // We don't need destruction since we use a finalizer. + static void destroy(JSC::JSCell*); + protected: - void finishCreation(JSGlobalObject*); + void finishCreation(VM&, JSGlobalObject*); + +private: + // This bit is set if any user modifies the constructor property Array.prototype. This is used to optimize species creation for JSArrays. + friend ArrayPrototypeAdaptiveInferredPropertyWatchpoint; + std::unique_ptr m_constructorWatchpoint; + std::unique_ptr m_constructorSpeciesWatchpoint; + bool m_didChangeConstructorOrSpeciesProperties = false; }; +EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState*); +EncodedJSValue JSC_HOST_CALL arrayProtoFuncValues(ExecState*); + } // namespace JSC #endif // ArrayPrototype_h diff --git a/Source/JavaScriptCore/runtime/ArrayStorage.h b/Source/JavaScriptCore/runtime/ArrayStorage.h index a0287c921..c93dc3bfd 100644 --- a/Source/JavaScriptCore/runtime/ArrayStorage.h +++ b/Source/JavaScriptCore/runtime/ArrayStorage.h @@ -32,7 +32,6 @@ #include "SparseArrayValueMap.h" #include "WriteBarrier.h" #include -#include namespace JSC { @@ -54,9 +53,10 @@ public: Butterfly* butterfly() { return reinterpret_cast(this); } IndexingHeader* indexingHeader() { return IndexingHeader::from(this); } + const IndexingHeader* indexingHeader() const { return IndexingHeader::from(this); } // We steal two fields from the indexing header: vectorLength and length. - unsigned length() { return indexingHeader()->publicLength(); } + unsigned length() const { return indexingHeader()->publicLength(); } void setLength(unsigned length) { indexingHeader()->setPublicLength(length); } unsigned vectorLength() { return indexingHeader()->vectorLength(); } void setVectorLength(unsigned length) { indexingHeader()->setVectorLength(length); } @@ -68,6 +68,11 @@ public: m_numValuesInVector = other.m_numValuesInVector; } + bool hasHoles() const + { + return m_numValuesInVector != length(); + } + bool inSparseMode() { return m_sparseMap && m_sparseMap->sparseMode(); diff --git a/Source/JavaScriptCore/runtime/BasicBlockLocation.cpp b/Source/JavaScriptCore/runtime/BasicBlockLocation.cpp new file mode 100644 index 000000000..d97b0370d --- /dev/null +++ b/Source/JavaScriptCore/runtime/BasicBlockLocation.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * Copyright (C) 2014 Saam Barati. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#include "config.h" +#include "BasicBlockLocation.h" + +#include "CCallHelpers.h" +#include +#include + +namespace JSC { + +BasicBlockLocation::BasicBlockLocation(int startOffset, int endOffset) + : m_startOffset(startOffset) + , m_endOffset(endOffset) + , m_executionCount(0) +{ +} + +void BasicBlockLocation::insertGap(int startOffset, int endOffset) +{ + std::pair gap(startOffset, endOffset); + if (!m_gaps.contains(gap)) + m_gaps.append(gap); +} + +Vector> BasicBlockLocation::getExecutedRanges() const +{ + Vector result; + Vector gaps = m_gaps; + int nextRangeStart = m_startOffset; + while (gaps.size()) { + Gap minGap(INT_MAX, 0); + unsigned minIdx = std::numeric_limits::max(); + for (unsigned idx = 0; idx < gaps.size(); idx++) { + // Because we know that the Gaps inside m_gaps aren't enclosed within one another, it suffices to just check the first element to test ordering. + if (gaps[idx].first < minGap.first) { + minGap = gaps[idx]; + minIdx = idx; + } + } + result.append(Gap(nextRangeStart, minGap.first - 1)); + nextRangeStart = minGap.second + 1; + gaps.remove(minIdx); + } + + result.append(Gap(nextRangeStart, m_endOffset)); + return result; +} + +void BasicBlockLocation::dumpData() const +{ + Vector executedRanges = getExecutedRanges(); + for (Gap gap : executedRanges) + dataLogF("\tBasicBlock: [%d, %d] hasExecuted: %s, executionCount:%zu\n", gap.first, gap.second, hasExecuted() ? "true" : "false", m_executionCount); +} + +#if ENABLE(JIT) +#if USE(JSVALUE64) +void BasicBlockLocation::emitExecuteCode(CCallHelpers& jit) const +{ + static_assert(sizeof(size_t) == 8, "Assuming size_t is 64 bits on 64 bit platforms."); + jit.add64(CCallHelpers::TrustedImm32(1), CCallHelpers::AbsoluteAddress(&m_executionCount)); +} +#else +void BasicBlockLocation::emitExecuteCode(CCallHelpers& jit, MacroAssembler::RegisterID scratch) const +{ + static_assert(sizeof(size_t) == 4, "Assuming size_t is 32 bits on 32 bit platforms."); + jit.load32(&m_executionCount, scratch); + CCallHelpers::Jump done = jit.branchAdd32(CCallHelpers::Zero, scratch, CCallHelpers::TrustedImm32(1), scratch); + jit.store32(scratch, bitwise_cast(&m_executionCount)); + done.link(&jit); +} +#endif // USE(JSVALUE64) +#endif // ENABLE(JIT) + +} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/BasicBlockLocation.h b/Source/JavaScriptCore/runtime/BasicBlockLocation.h new file mode 100644 index 000000000..a910f8911 --- /dev/null +++ b/Source/JavaScriptCore/runtime/BasicBlockLocation.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * Copyright (C) 2014 Saam Barati. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#ifndef BasicBlockLocation_h +#define BasicBlockLocation_h + +#include "MacroAssembler.h" +#include +#include +#include + +namespace JSC { + +class CCallHelpers; +class LLIntOffsetsExtractor; + +class BasicBlockLocation { +public: + typedef std::pair Gap; + + BasicBlockLocation(int startOffset = -1, int endOffset = -1); + + int startOffset() const { return m_startOffset; } + int endOffset() const { return m_endOffset; } + void setStartOffset(int startOffset) { m_startOffset = startOffset; } + void setEndOffset(int endOffset) { m_endOffset = endOffset; } + bool hasExecuted() const { return m_executionCount > 0; } + size_t executionCount() const { return m_executionCount; } + void insertGap(int, int); + Vector getExecutedRanges() const; + JS_EXPORT_PRIVATE void dumpData() const; +#if ENABLE(JIT) +#if USE(JSVALUE64) + void emitExecuteCode(CCallHelpers&) const; +#else + void emitExecuteCode(CCallHelpers&, MacroAssembler::RegisterID scratch) const; +#endif +#endif + +private: + friend class LLIntOffsetsExtractor; + + int m_startOffset; + int m_endOffset; + size_t m_executionCount; + Vector m_gaps; +}; + +} // namespace JSC + +#endif // BasicBlockLocation_h diff --git a/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h b/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h index 76def7138..951a3286c 100644 --- a/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h +++ b/Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. 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 @@ -38,6 +38,8 @@ public: : m_vm(&vm) , m_object(object) { + if (!m_object->structure(vm)->isDictionary()) + m_object->convertToDictionary(vm); } ~BatchedTransitionOptimizer() diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp index 453983b7a..c39ff7281 100644 --- a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp +++ b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2003, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2008, 2016 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,40 +23,36 @@ #include "BooleanPrototype.h" #include "JSGlobalObject.h" -#include "Operations.h" +#include "JSCInlines.h" namespace JSC { -ASSERT_HAS_TRIVIAL_DESTRUCTOR(BooleanConstructor); +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(BooleanConstructor); -const ClassInfo BooleanConstructor::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(BooleanConstructor) }; +const ClassInfo BooleanConstructor::s_info = { "Function", &Base::s_info, 0, CREATE_METHOD_TABLE(BooleanConstructor) }; -BooleanConstructor::BooleanConstructor(JSGlobalObject* globalObject, Structure* structure) - : InternalFunction(globalObject, structure) +BooleanConstructor::BooleanConstructor(VM& vm, Structure* structure) + : InternalFunction(vm, structure) { } -void BooleanConstructor::finishCreation(ExecState* exec, BooleanPrototype* booleanPrototype) +void BooleanConstructor::finishCreation(VM& vm, BooleanPrototype* booleanPrototype) { - Base::finishCreation(exec->vm(), booleanPrototype->classInfo()->className); - putDirectWithoutTransition(exec->vm(), exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly); + Base::finishCreation(vm, booleanPrototype->classInfo()->className); + putDirectWithoutTransition(vm, vm.propertyNames->prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly); // no. of arguments for constructor - putDirectWithoutTransition(exec->vm(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum); + putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(1), ReadOnly | DontDelete | DontEnum); } // ECMA 15.6.2 -JSObject* constructBoolean(ExecState* exec, const ArgList& args) -{ - BooleanObject* obj = BooleanObject::create(exec->vm(), asInternalFunction(exec->callee())->globalObject()->booleanObjectStructure()); - obj->setInternalValue(exec->vm(), jsBoolean(args.at(0).toBoolean(exec))); - return obj; -} - static EncodedJSValue JSC_HOST_CALL constructWithBooleanConstructor(ExecState* exec) { - ArgList args(exec); - return JSValue::encode(constructBoolean(exec, args)); + JSValue boolean = jsBoolean(exec->argument(0).toBoolean(exec)); + Structure* booleanStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), asInternalFunction(exec->callee())->globalObject()->booleanObjectStructure()); + BooleanObject* obj = BooleanObject::create(exec->vm(), booleanStructure); + obj->setInternalValue(exec->vm(), boolean); + return JSValue::encode(obj); } ConstructType BooleanConstructor::getConstructData(JSCell*, ConstructData& constructData) diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.h b/Source/JavaScriptCore/runtime/BooleanConstructor.h index 760d5d3b1..e49b9f9a2 100644 --- a/Source/JavaScriptCore/runtime/BooleanConstructor.h +++ b/Source/JavaScriptCore/runtime/BooleanConstructor.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2016 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,36 +26,36 @@ namespace JSC { class BooleanPrototype; +class GetterSetter; class BooleanConstructor : public InternalFunction { public: typedef InternalFunction Base; - static BooleanConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, BooleanPrototype* booleanPrototype) + static BooleanConstructor* create(VM& vm, Structure* structure, BooleanPrototype* booleanPrototype, GetterSetter*) { - BooleanConstructor* constructor = new (NotNull, allocateCell(*exec->heap())) BooleanConstructor(globalObject, structure); - constructor->finishCreation(exec, booleanPrototype); + BooleanConstructor* constructor = new (NotNull, allocateCell(vm.heap)) BooleanConstructor(vm, structure); + constructor->finishCreation(vm, booleanPrototype); return constructor; } - static const ClassInfo s_info; + DECLARE_INFO; static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); } protected: - void finishCreation(ExecState*, BooleanPrototype*); + void finishCreation(VM&, BooleanPrototype*); private: - BooleanConstructor(JSGlobalObject*, Structure*); + BooleanConstructor(VM&, Structure*); static ConstructType getConstructData(JSCell*, ConstructData&); static CallType getCallData(JSCell*, CallData&); }; JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSGlobalObject*, JSValue); -JSObject* constructBoolean(ExecState*, const ArgList&); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/BooleanObject.cpp b/Source/JavaScriptCore/runtime/BooleanObject.cpp index 3f7f2f621..28cad6ae7 100644 --- a/Source/JavaScriptCore/runtime/BooleanObject.cpp +++ b/Source/JavaScriptCore/runtime/BooleanObject.cpp @@ -22,13 +22,13 @@ #include "BooleanObject.h" #include "JSScope.h" -#include "Operations.h" +#include "JSCInlines.h" namespace JSC { -ASSERT_HAS_TRIVIAL_DESTRUCTOR(BooleanObject); +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(BooleanObject); -const ClassInfo BooleanObject::s_info = { "Boolean", &JSWrapperObject::s_info, 0, 0, CREATE_METHOD_TABLE(BooleanObject) }; +const ClassInfo BooleanObject::s_info = { "Boolean", &JSWrapperObject::s_info, 0, CREATE_METHOD_TABLE(BooleanObject) }; BooleanObject::BooleanObject(VM& vm, Structure* structure) : JSWrapperObject(vm, structure) @@ -38,7 +38,7 @@ BooleanObject::BooleanObject(VM& vm, Structure* structure) void BooleanObject::finishCreation(VM& vm) { Base::finishCreation(vm); - ASSERT(inherits(&s_info)); + ASSERT(inherits(info())); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/BooleanObject.h b/Source/JavaScriptCore/runtime/BooleanObject.h index 299f34174..6944db496 100644 --- a/Source/JavaScriptCore/runtime/BooleanObject.h +++ b/Source/JavaScriptCore/runtime/BooleanObject.h @@ -40,11 +40,11 @@ public: return boolean; } - static JS_EXPORTDATA const ClassInfo s_info; + DECLARE_EXPORT_INFO; static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); } }; @@ -52,7 +52,7 @@ BooleanObject* asBooleanObject(JSValue); inline BooleanObject* asBooleanObject(JSValue value) { - ASSERT(asObject(value)->inherits(&BooleanObject::s_info)); + ASSERT(asObject(value)->inherits(BooleanObject::info())); return static_cast(asObject(value)); } diff --git a/Source/JavaScriptCore/runtime/BooleanPrototype.cpp b/Source/JavaScriptCore/runtime/BooleanPrototype.cpp index a5b8390a8..be737ae5a 100644 --- a/Source/JavaScriptCore/runtime/BooleanPrototype.cpp +++ b/Source/JavaScriptCore/runtime/BooleanPrototype.cpp @@ -26,7 +26,7 @@ #include "JSFunction.h" #include "JSString.h" #include "ObjectPrototype.h" -#include "Operations.h" +#include "JSCInlines.h" namespace JSC { @@ -39,7 +39,7 @@ static EncodedJSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState*); namespace JSC { -const ClassInfo BooleanPrototype::s_info = { "Boolean", &BooleanObject::s_info, 0, ExecState::booleanPrototypeTable, CREATE_METHOD_TABLE(BooleanPrototype) }; +const ClassInfo BooleanPrototype::s_info = { "Boolean", &BooleanObject::s_info, &booleanPrototypeTable, CREATE_METHOD_TABLE(BooleanPrototype) }; /* Source for BooleanPrototype.lut.h @begin booleanPrototypeTable @@ -48,29 +48,24 @@ const ClassInfo BooleanPrototype::s_info = { "Boolean", &BooleanObject::s_info, @end */ -ASSERT_HAS_TRIVIAL_DESTRUCTOR(BooleanPrototype); +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(BooleanPrototype); -BooleanPrototype::BooleanPrototype(ExecState* exec, Structure* structure) - : BooleanObject(exec->vm(), structure) +BooleanPrototype::BooleanPrototype(VM& vm, Structure* structure) + : BooleanObject(vm, structure) { } -void BooleanPrototype::finishCreation(ExecState* exec, JSGlobalObject*) +void BooleanPrototype::finishCreation(VM& vm, JSGlobalObject*) { - Base::finishCreation(exec->vm()); - setInternalValue(exec->vm(), jsBoolean(false)); + Base::finishCreation(vm); + setInternalValue(vm, jsBoolean(false)); - ASSERT(inherits(&s_info)); + ASSERT(inherits(info())); } -bool BooleanPrototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot &slot) +bool BooleanPrototype::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot &slot) { - return getStaticFunctionSlot(exec, ExecState::booleanPrototypeTable(exec), jsCast(cell), propertyName, slot); -} - -bool BooleanPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) -{ - return getStaticFunctionDescriptor(exec, ExecState::booleanPrototypeTable(exec), jsCast(object), propertyName, descriptor); + return getStaticFunctionSlot(exec, booleanPrototypeTable, jsCast(object), propertyName, slot); } // ------------------------------ Functions --------------------------- @@ -78,14 +73,14 @@ bool BooleanPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exe EncodedJSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState* exec) { VM* vm = &exec->vm(); - JSValue thisValue = exec->hostThisValue(); + JSValue thisValue = exec->thisValue(); if (thisValue == jsBoolean(false)) return JSValue::encode(vm->smallStrings.falseString()); if (thisValue == jsBoolean(true)) return JSValue::encode(vm->smallStrings.trueString()); - if (!thisValue.inherits(&BooleanObject::s_info)) + if (!thisValue.inherits(BooleanObject::info())) return throwVMTypeError(exec); if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false)) @@ -97,11 +92,11 @@ EncodedJSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState* exec) EncodedJSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState* exec) { - JSValue thisValue = exec->hostThisValue(); + JSValue thisValue = exec->thisValue(); if (thisValue.isBoolean()) return JSValue::encode(thisValue); - if (!thisValue.inherits(&BooleanObject::s_info)) + if (!thisValue.inherits(BooleanObject::info())) return throwVMTypeError(exec); return JSValue::encode(asBooleanObject(thisValue)->internalValue()); diff --git a/Source/JavaScriptCore/runtime/BooleanPrototype.h b/Source/JavaScriptCore/runtime/BooleanPrototype.h index 43b81cb61..6d8fc5e81 100644 --- a/Source/JavaScriptCore/runtime/BooleanPrototype.h +++ b/Source/JavaScriptCore/runtime/BooleanPrototype.h @@ -28,30 +28,28 @@ namespace JSC { class BooleanPrototype : public BooleanObject { public: typedef BooleanObject Base; + static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot; - static BooleanPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure) + static BooleanPrototype* create(VM& vm, JSGlobalObject* globalObject, Structure* structure) { - BooleanPrototype* prototype = new (NotNull, allocateCell(*exec->heap())) BooleanPrototype(exec, structure); - prototype->finishCreation(exec, globalObject); + BooleanPrototype* prototype = new (NotNull, allocateCell(vm.heap)) BooleanPrototype(vm, structure); + prototype->finishCreation(vm, globalObject); return prototype; } - static const ClassInfo s_info; + DECLARE_INFO; static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) { - return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); } protected: - void finishCreation(ExecState*, JSGlobalObject*); - static const unsigned StructureFlags = OverridesGetOwnPropertySlot | BooleanObject::StructureFlags; + void finishCreation(VM&, JSGlobalObject*); private: - BooleanPrototype(ExecState*, Structure*); - static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&); - - static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); + BooleanPrototype(VM&, Structure*); + static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/BundlePath.h b/Source/JavaScriptCore/runtime/BundlePath.h new file mode 100644 index 000000000..c8c694832 --- /dev/null +++ b/Source/JavaScriptCore/runtime/BundlePath.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#ifndef BundlePath_h +#define BundlePath_h + +#include +#include + +namespace JSC { + +const CString& bundlePath(); + +} // namespace JSC + +#endif // BundlePath_h + diff --git a/Source/JavaScriptCore/runtime/Butterfly.h b/Source/JavaScriptCore/runtime/Butterfly.h index eb6d82a76..20dccd9b6 100644 --- a/Source/JavaScriptCore/runtime/Butterfly.h +++ b/Source/JavaScriptCore/runtime/Butterfly.h @@ -30,7 +30,6 @@ #include "PropertyOffset.h" #include "PropertyStorage.h" #include -#include namespace JSC { @@ -71,7 +70,7 @@ private: }; typedef ContiguousData ContiguousDoubles; -typedef ContiguousData > ContiguousJSValues; +typedef ContiguousData> ContiguousJSValues; class Butterfly { WTF_MAKE_NONCOPYABLE(Butterfly); @@ -101,13 +100,14 @@ public: char* pointer() { return reinterpret_cast(this); } static ptrdiff_t offsetOfIndexingHeader() { return IndexingHeader::offsetOfIndexingHeader(); } + static ptrdiff_t offsetOfArrayBuffer() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfArrayBuffer(); } static ptrdiff_t offsetOfPublicLength() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfPublicLength(); } static ptrdiff_t offsetOfVectorLength() { return offsetOfIndexingHeader() + IndexingHeader::offsetOfVectorLength(); } - static Butterfly* createUninitialized(VM&, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes); + static Butterfly* createUninitialized(VM&, JSCell* intendedOwner, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes); - static Butterfly* create(VM&, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, const IndexingHeader&, size_t indexingPayloadSizeInBytes); - static Butterfly* create(VM&, Structure*); + static Butterfly* create(VM&, JSCell* intendedOwner, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, const IndexingHeader&, size_t indexingPayloadSizeInBytes); + static Butterfly* create(VM&, JSCell* intendedOwner, Structure*); static Butterfly* createUninitializedDuringCollection(CopyVisitor&, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes); IndexingHeader* indexingHeader() { return IndexingHeader::from(this); } @@ -123,10 +123,10 @@ public: template T* indexingPayload() { return reinterpret_cast_ptr(this); } ArrayStorage* arrayStorage() { return indexingPayload(); } - ContiguousJSValues contiguousInt32() { return ContiguousJSValues(indexingPayload >(), vectorLength()); } + ContiguousJSValues contiguousInt32() { return ContiguousJSValues(indexingPayload>(), vectorLength()); } ContiguousDoubles contiguousDouble() { return ContiguousDoubles(indexingPayload(), vectorLength()); } - ContiguousJSValues contiguous() { return ContiguousJSValues(indexingPayload >(), vectorLength()); } + ContiguousJSValues contiguous() { return ContiguousJSValues(indexingPayload>(), vectorLength()); } static Butterfly* fromContiguous(WriteBarrier* contiguous) { @@ -147,20 +147,21 @@ public: void* base(size_t preCapacity, size_t propertyCapacity) { return propertyStorage() - propertyCapacity - preCapacity; } void* base(Structure*); - static Butterfly* createOrGrowArrayRight(Butterfly*, VM&, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes); + static Butterfly* createOrGrowArrayRight( + Butterfly*, VM&, JSCell* intendedOwner, Structure* oldStructure, + size_t propertyCapacity, bool hadIndexingHeader, + size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes); // The butterfly reallocation methods perform the reallocation itself but do not change any // of the meta-data to reflect that the reallocation occurred. Note that this set of // methods is not exhaustive and is not intended to encapsulate all possible allocation // modes of butterflies - there are code paths that allocate butterflies by calling // directly into Heap::tryAllocateStorage. - Butterfly* growPropertyStorage(VM&, size_t preCapacity, size_t oldPropertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes, size_t newPropertyCapacity); - Butterfly* growPropertyStorage(VM&, Structure* oldStructure, size_t oldPropertyCapacity, size_t newPropertyCapacity); - Butterfly* growPropertyStorage(VM&, Structure* oldStructure, size_t newPropertyCapacity); - Butterfly* growArrayRight(VM&, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes); // Assumes that preCapacity is zero, and asserts as much. - Butterfly* growArrayRight(VM&, Structure*, size_t newIndexingPayloadSizeInBytes); - Butterfly* resizeArray(VM&, size_t propertyCapacity, bool oldHasIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newPreCapacity, bool newHasIndexingHeader, size_t newIndexingPayloadSizeInBytes); - Butterfly* resizeArray(VM&, Structure*, size_t newPreCapacity, size_t newIndexingPayloadSizeInBytes); // Assumes that you're not changing whether or not the object has an indexing header. + static Butterfly* createOrGrowPropertyStorage(Butterfly*, VM&, JSCell* intendedOwner, Structure*, size_t oldPropertyCapacity, size_t newPropertyCapacity); + Butterfly* growArrayRight(VM&, JSCell* intendedOwner, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes); // Assumes that preCapacity is zero, and asserts as much. + Butterfly* growArrayRight(VM&, JSCell* intendedOwner, Structure*, size_t newIndexingPayloadSizeInBytes); + Butterfly* resizeArray(VM&, JSCell* intendedOwner, size_t propertyCapacity, bool oldHasIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newPreCapacity, bool newHasIndexingHeader, size_t newIndexingPayloadSizeInBytes); + Butterfly* resizeArray(VM&, JSCell* intendedOwner, Structure*, size_t newPreCapacity, size_t newIndexingPayloadSizeInBytes); // Assumes that you're not changing whether or not the object has an indexing header. Butterfly* unshift(Structure*, size_t numberOfSlots); Butterfly* shift(Structure*, size_t numberOfSlots); }; diff --git a/Source/JavaScriptCore/runtime/ButterflyInlines.h b/Source/JavaScriptCore/runtime/ButterflyInlines.h index a0e2af19d..3fd8dc139 100644 --- a/Source/JavaScriptCore/runtime/ButterflyInlines.h +++ b/Source/JavaScriptCore/runtime/ButterflyInlines.h @@ -35,27 +35,30 @@ namespace JSC { -inline Butterfly* Butterfly::createUninitialized(VM& vm, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes) +inline Butterfly* Butterfly::createUninitialized(VM& vm, JSCell* intendedOwner, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes) { void* temp; size_t size = totalSize(preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); - RELEASE_ASSERT(vm.heap.tryAllocateStorage(size, &temp)); + RELEASE_ASSERT(vm.heap.tryAllocateStorage(intendedOwner, size, &temp)); Butterfly* result = fromBase(temp, preCapacity, propertyCapacity); return result; } -inline Butterfly* Butterfly::create(VM& vm, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, const IndexingHeader& indexingHeader, size_t indexingPayloadSizeInBytes) +inline Butterfly* Butterfly::create(VM& vm, JSCell* intendedOwner, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, const IndexingHeader& indexingHeader, size_t indexingPayloadSizeInBytes) { Butterfly* result = createUninitialized( - vm, preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); + vm, intendedOwner, preCapacity, propertyCapacity, hasIndexingHeader, + indexingPayloadSizeInBytes); if (hasIndexingHeader) *result->indexingHeader() = indexingHeader; return result; } -inline Butterfly* Butterfly::create(VM& vm, Structure* structure) +inline Butterfly* Butterfly::create(VM& vm, JSCell* intendedOwner, Structure* structure) { - return create(vm, 0, structure->outOfLineCapacity(), hasIndexingHeader(structure->indexingType()), IndexingHeader(), 0); + return create( + vm, intendedOwner, 0, structure->outOfLineCapacity(), + structure->hasIndexingHeader(intendedOwner), IndexingHeader(), 0); } inline Butterfly* Butterfly::createUninitializedDuringCollection(CopyVisitor& visitor, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes) @@ -72,63 +75,74 @@ inline void* Butterfly::base(Structure* structure) return base(indexingHeader()->preCapacity(structure), structure->outOfLineCapacity()); } -inline Butterfly* Butterfly::growPropertyStorage(VM& vm, size_t preCapacity, size_t oldPropertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes, size_t newPropertyCapacity) +inline Butterfly* Butterfly::createOrGrowPropertyStorage( + Butterfly* oldButterfly, VM& vm, JSCell* intendedOwner, Structure* structure, size_t oldPropertyCapacity, size_t newPropertyCapacity) { RELEASE_ASSERT(newPropertyCapacity > oldPropertyCapacity); + if (!oldButterfly) + return create(vm, intendedOwner, 0, newPropertyCapacity, false, IndexingHeader(), 0); + + size_t preCapacity = oldButterfly->indexingHeader()->preCapacity(structure); + size_t indexingPayloadSizeInBytes = oldButterfly->indexingHeader()->indexingPayloadSizeInBytes(structure); + bool hasIndexingHeader = structure->hasIndexingHeader(intendedOwner); Butterfly* result = createUninitialized( - vm, preCapacity, newPropertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); + vm, intendedOwner, preCapacity, newPropertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); memcpy( result->propertyStorage() - oldPropertyCapacity, - propertyStorage() - oldPropertyCapacity, + oldButterfly->propertyStorage() - oldPropertyCapacity, totalSize(0, oldPropertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes)); return result; } -inline Butterfly* Butterfly::growPropertyStorage(VM& vm, Structure* structure, size_t oldPropertyCapacity, size_t newPropertyCapacity) -{ - return growPropertyStorage( - vm, indexingHeader()->preCapacity(structure), oldPropertyCapacity, - hasIndexingHeader(structure->indexingType()), - indexingHeader()->indexingPayloadSizeInBytes(structure), newPropertyCapacity); -} - -inline Butterfly* Butterfly::growPropertyStorage(VM& vm, Structure* oldStructure, size_t newPropertyCapacity) +inline Butterfly* Butterfly::createOrGrowArrayRight( + Butterfly* oldButterfly, VM& vm, JSCell* intendedOwner, Structure* oldStructure, + size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, + size_t newIndexingPayloadSizeInBytes) { - return growPropertyStorage( - vm, oldStructure, oldStructure->outOfLineCapacity(), newPropertyCapacity); -} - -inline Butterfly* Butterfly::createOrGrowArrayRight(Butterfly* oldButterfly, VM& vm, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes) -{ - if (!oldButterfly) - return create(vm, 0, propertyCapacity, true, IndexingHeader(), newIndexingPayloadSizeInBytes); - return oldButterfly->growArrayRight(vm, oldStructure, propertyCapacity, hadIndexingHeader, oldIndexingPayloadSizeInBytes, newIndexingPayloadSizeInBytes); + if (!oldButterfly) { + return create( + vm, intendedOwner, 0, propertyCapacity, true, IndexingHeader(), + newIndexingPayloadSizeInBytes); + } + return oldButterfly->growArrayRight( + vm, intendedOwner, oldStructure, propertyCapacity, hadIndexingHeader, + oldIndexingPayloadSizeInBytes, newIndexingPayloadSizeInBytes); } -inline Butterfly* Butterfly::growArrayRight(VM& vm, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes) +inline Butterfly* Butterfly::growArrayRight( + VM& vm, JSCell* intendedOwner, Structure* oldStructure, size_t propertyCapacity, + bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, + size_t newIndexingPayloadSizeInBytes) { ASSERT_UNUSED(oldStructure, !indexingHeader()->preCapacity(oldStructure)); - ASSERT_UNUSED(oldStructure, hadIndexingHeader == hasIndexingHeader(oldStructure->indexingType())); + ASSERT_UNUSED(oldStructure, hadIndexingHeader == oldStructure->hasIndexingHeader(intendedOwner)); void* theBase = base(0, propertyCapacity); size_t oldSize = totalSize(0, propertyCapacity, hadIndexingHeader, oldIndexingPayloadSizeInBytes); size_t newSize = totalSize(0, propertyCapacity, true, newIndexingPayloadSizeInBytes); - if (!vm.heap.tryReallocateStorage(&theBase, oldSize, newSize)) + if (!vm.heap.tryReallocateStorage(intendedOwner, &theBase, oldSize, newSize)) return 0; return fromBase(theBase, 0, propertyCapacity); } -inline Butterfly* Butterfly::growArrayRight(VM& vm, Structure* oldStructure, size_t newIndexingPayloadSizeInBytes) +inline Butterfly* Butterfly::growArrayRight( + VM& vm, JSCell* intendedOwner, Structure* oldStructure, + size_t newIndexingPayloadSizeInBytes) { return growArrayRight( - vm, oldStructure, oldStructure->outOfLineCapacity(), - hasIndexingHeader(oldStructure->indexingType()), - indexingHeader()->indexingPayloadSizeInBytes(oldStructure), newIndexingPayloadSizeInBytes); + vm, intendedOwner, oldStructure, oldStructure->outOfLineCapacity(), + oldStructure->hasIndexingHeader(intendedOwner), + indexingHeader()->indexingPayloadSizeInBytes(oldStructure), + newIndexingPayloadSizeInBytes); } -inline Butterfly* Butterfly::resizeArray(VM& vm, size_t propertyCapacity, bool oldHasIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newPreCapacity, bool newHasIndexingHeader, size_t newIndexingPayloadSizeInBytes) +inline Butterfly* Butterfly::resizeArray( + VM& vm, JSCell* intendedOwner, size_t propertyCapacity, bool oldHasIndexingHeader, + size_t oldIndexingPayloadSizeInBytes, size_t newPreCapacity, bool newHasIndexingHeader, + size_t newIndexingPayloadSizeInBytes) { Butterfly* result = createUninitialized( - vm, newPreCapacity, propertyCapacity, newHasIndexingHeader, newIndexingPayloadSizeInBytes); + vm, intendedOwner, newPreCapacity, propertyCapacity, newHasIndexingHeader, + newIndexingPayloadSizeInBytes); // FIXME: This could be made much more efficient if we used the property size, // not the capacity. void* to = result->propertyStorage() - propertyCapacity; @@ -140,18 +154,20 @@ inline Butterfly* Butterfly::resizeArray(VM& vm, size_t propertyCapacity, bool o return result; } -inline Butterfly* Butterfly::resizeArray(VM& vm, Structure* structure, size_t newPreCapacity, size_t newIndexingPayloadSizeInBytes) +inline Butterfly* Butterfly::resizeArray( + VM& vm, JSCell* intendedOwner, Structure* structure, size_t newPreCapacity, + size_t newIndexingPayloadSizeInBytes) { - bool hasIndexingHeader = JSC::hasIndexingHeader(structure->indexingType()); + bool hasIndexingHeader = structure->hasIndexingHeader(intendedOwner); return resizeArray( - vm, structure->outOfLineCapacity(), hasIndexingHeader, + vm, intendedOwner, structure->outOfLineCapacity(), hasIndexingHeader, indexingHeader()->indexingPayloadSizeInBytes(structure), newPreCapacity, hasIndexingHeader, newIndexingPayloadSizeInBytes); } inline Butterfly* Butterfly::unshift(Structure* structure, size_t numberOfSlots) { - ASSERT(hasArrayStorage(structure->indexingType())); + ASSERT(hasAnyArrayStorage(structure->indexingType())); ASSERT(numberOfSlots <= indexingHeader()->preCapacity(structure)); unsigned propertyCapacity = structure->outOfLineCapacity(); // FIXME: It would probably be wise to rewrite this as a loop since (1) we know in which @@ -170,7 +186,7 @@ inline Butterfly* Butterfly::unshift(Structure* structure, size_t numberOfSlots) inline Butterfly* Butterfly::shift(Structure* structure, size_t numberOfSlots) { - ASSERT(hasArrayStorage(structure->indexingType())); + ASSERT(hasAnyArrayStorage(structure->indexingType())); unsigned propertyCapacity = structure->outOfLineCapacity(); // FIXME: See comment in unshift(), above. memmove( diff --git a/Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h b/Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h deleted file mode 100644 index 392d64fa5..000000000 --- a/Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. - */ - -#ifndef CachedTranscendentalFunction_h -#define CachedTranscendentalFunction_h - -#include "JSCJSValue.h" - -namespace JSC { - -typedef double (*TranscendentalFunctionPtr)(double); - -// CachedTranscendentalFunction provides a generic mechanism to cache results -// for pure functions with the signature "double func(double)", and where NaN -// maps to NaN. -template -class CachedTranscendentalFunction { - struct CacheEntry { - double operand; - double result; - }; - -public: - CachedTranscendentalFunction() - : m_cache(0) - { - } - - ~CachedTranscendentalFunction() - { - if (m_cache) - fastFree(m_cache); - } - - JSValue operator() (double operand) - { - if (UNLIKELY(!m_cache)) - initialize(); - CacheEntry* entry = &m_cache[hash(operand)]; - - if (entry->operand == operand) - return jsDoubleNumber(entry->result); - double result = orignalFunction(operand); - entry->operand = operand; - entry->result = result; - return jsDoubleNumber(result); - } - -private: - void initialize() - { - // Lazily allocate the table, populate with NaN->NaN mapping. - m_cache = static_cast(fastMalloc(s_cacheSize * sizeof(CacheEntry))); - for (unsigned x = 0; x < s_cacheSize; ++x) { - m_cache[x].operand = QNaN; - m_cache[x].result = QNaN; - } - } - - static unsigned hash(double d) - { - union doubleAndUInt64 { - double d; - uint32_t is[2]; - } u; - u.d = d; - - unsigned x = u.is[0] ^ u.is[1]; - x = (x >> 20) ^ (x >> 8); - return x & (s_cacheSize - 1); - } - - static const unsigned s_cacheSize = 0x1000; - CacheEntry* m_cache; -}; - -} - -#endif // CachedTranscendentalFunction_h diff --git a/Source/JavaScriptCore/runtime/CallData.cpp b/Source/JavaScriptCore/runtime/CallData.cpp index 8e1d19486..42c80ddb6 100644 --- a/Source/JavaScriptCore/runtime/CallData.cpp +++ b/Source/JavaScriptCore/runtime/CallData.cpp @@ -28,16 +28,40 @@ #include "Executable.h" #include "Interpreter.h" +#include "JSCInlines.h" #include "JSFunction.h" -#include "Operations.h" +#include "ScriptProfilingScope.h" namespace JSC { JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args) { ASSERT(callType == CallTypeJS || callType == CallTypeHost); - ASSERT(isValidThisObject(thisValue, exec)); return exec->interpreter()->executeCall(exec, asObject(functionObject), callType, callData, thisValue, args); } +JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args, NakedPtr& returnedException) +{ + JSValue result = call(exec, functionObject, callType, callData, thisValue, args); + if (exec->hadException()) { + returnedException = exec->exception(); + exec->clearException(); + return jsUndefined(); + } + RELEASE_ASSERT(result); + return result; +} + +JSValue profiledCall(ExecState* exec, ProfilingReason reason, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args) +{ + ScriptProfilingScope profilingScope(exec->vmEntryGlobalObject(), reason); + return call(exec, functionObject, callType, callData, thisValue, args); +} + +JSValue profiledCall(ExecState* exec, ProfilingReason reason, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args, NakedPtr& returnedException) +{ + ScriptProfilingScope profilingScope(exec->vmEntryGlobalObject(), reason); + return call(exec, functionObject, callType, callData, thisValue, args, returnedException); +} + } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/CallData.h b/Source/JavaScriptCore/runtime/CallData.h index 3bbac734f..45dbfbcc3 100644 --- a/Source/JavaScriptCore/runtime/CallData.h +++ b/Source/JavaScriptCore/runtime/CallData.h @@ -10,7 +10,7 @@ * 2. 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * @@ -30,10 +30,12 @@ #define CallData_h #include "JSCJSValue.h" +#include namespace JSC { class ArgList; +class Exception; class ExecState; class FunctionExecutable; class JSObject; @@ -57,7 +59,17 @@ union CallData { } js; }; +enum class ProfilingReason { + API, + Microtask, + Other +}; + JS_EXPORT_PRIVATE JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&); +JS_EXPORT_PRIVATE JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&, NakedPtr& returnedException); + +JS_EXPORT_PRIVATE JSValue profiledCall(ExecState*, ProfilingReason, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&); +JS_EXPORT_PRIVATE JSValue profiledCall(ExecState*, ProfilingReason, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&, NakedPtr& returnedException); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ClassInfo.h b/Source/JavaScriptCore/runtime/ClassInfo.h index af1d71e13..84fc11a3c 100644 --- a/Source/JavaScriptCore/runtime/ClassInfo.h +++ b/Source/JavaScriptCore/runtime/ClassInfo.h @@ -25,11 +25,12 @@ #include "CallFrame.h" #include "ConstructData.h" +#include "CopyToken.h" #include "JSCell.h" namespace JSC { -class HashEntry; +class JSArrayBufferView; struct HashTable; struct MethodTable { @@ -39,7 +40,7 @@ struct MethodTable { typedef void (*VisitChildrenFunctionPtr)(JSCell*, SlotVisitor&); VisitChildrenFunctionPtr visitChildren; - typedef void (*CopyBackingStoreFunctionPtr)(JSCell*, CopyVisitor&); + typedef void (*CopyBackingStoreFunctionPtr)(JSCell*, CopyVisitor&, CopyToken); CopyBackingStoreFunctionPtr copyBackingStore; typedef CallType (*GetCallDataFunctionPtr)(JSCell*, CallData&); @@ -60,14 +61,14 @@ struct MethodTable { typedef bool (*DeletePropertyByIndexFunctionPtr)(JSCell*, ExecState*, unsigned); DeletePropertyByIndexFunctionPtr deletePropertyByIndex; - typedef bool (*GetOwnPropertySlotFunctionPtr)(JSCell*, ExecState*, PropertyName, PropertySlot&); + typedef bool (*GetOwnPropertySlotFunctionPtr)(JSObject*, ExecState*, PropertyName, PropertySlot&); GetOwnPropertySlotFunctionPtr getOwnPropertySlot; - typedef bool (*GetOwnPropertySlotByIndexFunctionPtr)(JSCell*, ExecState*, unsigned, PropertySlot&); + typedef bool (*GetOwnPropertySlotByIndexFunctionPtr)(JSObject*, ExecState*, unsigned, PropertySlot&); GetOwnPropertySlotByIndexFunctionPtr getOwnPropertySlotByIndex; - typedef JSObject* (*ToThisObjectFunctionPtr)(JSCell*, ExecState*); - ToThisObjectFunctionPtr toThisObject; + typedef JSValue (*ToThisFunctionPtr)(JSCell*, ExecState*, ECMAMode); + ToThisFunctionPtr toThis; typedef JSValue (*DefaultValueFunctionPtr)(const JSObject*, ExecState*, PreferredPrimitiveType); DefaultValueFunctionPtr defaultValue; @@ -81,20 +82,32 @@ struct MethodTable { typedef void (*GetPropertyNamesFunctionPtr)(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); GetPropertyNamesFunctionPtr getPropertyNames; + typedef uint32_t (*GetEnumerableLengthFunctionPtr)(ExecState*, JSObject*); + GetEnumerableLengthFunctionPtr getEnumerableLength; + + GetPropertyNamesFunctionPtr getStructurePropertyNames; + GetPropertyNamesFunctionPtr getGenericPropertyNames; + typedef String (*ClassNameFunctionPtr)(const JSObject*); ClassNameFunctionPtr className; typedef bool (*CustomHasInstanceFunctionPtr)(JSObject*, ExecState*, JSValue); CustomHasInstanceFunctionPtr customHasInstance; - typedef void (*PutWithAttributesFunctionPtr)(JSObject*, ExecState*, PropertyName propertyName, JSValue, unsigned attributes); - PutWithAttributesFunctionPtr putDirectVirtual; - - typedef bool (*DefineOwnPropertyFunctionPtr)(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool); + typedef bool (*DefineOwnPropertyFunctionPtr)(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool); DefineOwnPropertyFunctionPtr defineOwnProperty; - typedef bool (*GetOwnPropertyDescriptorFunctionPtr)(JSObject*, ExecState*, PropertyName, PropertyDescriptor&); - GetOwnPropertyDescriptorFunctionPtr getOwnPropertyDescriptor; + typedef ArrayBuffer* (*SlowDownAndWasteMemory)(JSArrayBufferView*); + SlowDownAndWasteMemory slowDownAndWasteMemory; + + typedef PassRefPtr (*GetTypedArrayImpl)(JSArrayBufferView*); + GetTypedArrayImpl getTypedArrayImpl; + + typedef void (*DumpToStreamFunctionPtr)(const JSCell*, PrintStream&); + DumpToStreamFunctionPtr dumpToStream; + + typedef size_t (*EstimatedSizeFunctionPtr)(JSCell*); + EstimatedSizeFunctionPtr estimatedSize; }; #define CREATE_MEMBER_CHECKER(member) \ @@ -128,41 +141,32 @@ struct MethodTable { &ClassName::deletePropertyByIndex, \ &ClassName::getOwnPropertySlot, \ &ClassName::getOwnPropertySlotByIndex, \ - &ClassName::toThisObject, \ + &ClassName::toThis, \ &ClassName::defaultValue, \ &ClassName::getOwnPropertyNames, \ &ClassName::getOwnNonIndexPropertyNames, \ &ClassName::getPropertyNames, \ + &ClassName::getEnumerableLength, \ + &ClassName::getStructurePropertyNames, \ + &ClassName::getGenericPropertyNames, \ &ClassName::className, \ &ClassName::customHasInstance, \ - &ClassName::putDirectVirtual, \ &ClassName::defineOwnProperty, \ - &ClassName::getOwnPropertyDescriptor, \ + &ClassName::slowDownAndWasteMemory, \ + &ClassName::getTypedArrayImpl, \ + &ClassName::dumpToStream, \ + &ClassName::estimatedSize \ }, \ ClassName::TypedArrayStorageType struct ClassInfo { - /** - * A string denoting the class name. Example: "Window". - */ + // A string denoting the class name. Example: "Window". const char* className; - /** - * Pointer to the class information of the base class. - * 0L if there is none. - */ + // Pointer to the class information of the base class. + // nullptrif there is none. const ClassInfo* parentClass; - /** - * Static hash-table of properties. - * For classes that can be used from multiple threads, it is accessed via a getter function that would typically return a pointer to thread-specific value. - */ - const HashTable* propHashTable(ExecState* exec) const - { - if (classPropHashTableGetterFunction) - return classPropHashTableGetterFunction(exec); - return staticPropHashTable; - } - + bool isSubClassOf(const ClassInfo* other) const { for (const ClassInfo* ci = this; ci; ci = ci->parentClass) { @@ -175,15 +179,15 @@ struct ClassInfo { bool hasStaticProperties() const { for (const ClassInfo* ci = this; ci; ci = ci->parentClass) { - if (ci->staticPropHashTable || ci->classPropHashTableGetterFunction) + if (ci->staticPropHashTable) return true; } return false; } + JS_EXPORT_PRIVATE bool hasStaticSetterOrReadonlyProperties() const; + const HashTable* staticPropHashTable; - typedef const HashTable* (*ClassPropHashTableGetterFunction)(ExecState*); - const ClassPropHashTableGetterFunction classPropHashTableGetterFunction; MethodTable methodTable; diff --git a/Source/JavaScriptCore/runtime/ClonedArguments.cpp b/Source/JavaScriptCore/runtime/ClonedArguments.cpp new file mode 100644 index 000000000..8241d6e0c --- /dev/null +++ b/Source/JavaScriptCore/runtime/ClonedArguments.cpp @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#include "config.h" +#include "ClonedArguments.h" + +#include "GetterSetter.h" +#include "InlineCallFrame.h" +#include "JSCInlines.h" + +namespace JSC { + +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ClonedArguments); + +const ClassInfo ClonedArguments::s_info = { "Arguments", &Base::s_info, 0, CREATE_METHOD_TABLE(ClonedArguments) }; + +ClonedArguments::ClonedArguments(VM& vm, Structure* structure) + : Base(vm, structure, nullptr) +{ +} + +ClonedArguments* ClonedArguments::createEmpty( + VM& vm, Structure* structure, JSFunction* callee) +{ + ClonedArguments* result = + new (NotNull, allocateCell(vm.heap)) + ClonedArguments(vm, structure); + result->finishCreation(vm); + result->m_callee.set(vm, result, callee); + return result; +} + +ClonedArguments* ClonedArguments::createEmpty(ExecState* exec, JSFunction* callee) +{ + // NB. Some clients might expect that the global object of of this object is the global object + // of the callee. We don't do this for now, but maybe we should. + return createEmpty( + exec->vm(), exec->lexicalGlobalObject()->outOfBandArgumentsStructure(), callee); +} + +ClonedArguments* ClonedArguments::createWithInlineFrame(ExecState* myFrame, ExecState* targetFrame, InlineCallFrame* inlineCallFrame, ArgumentsMode mode) +{ + VM& vm = myFrame->vm(); + + JSFunction* callee; + + if (inlineCallFrame) + callee = jsCast(inlineCallFrame->calleeRecovery.recover(targetFrame)); + else + callee = jsCast(targetFrame->callee()); + + ClonedArguments* result = createEmpty(myFrame, callee); + + unsigned length = 0; // Initialize because VC needs it. + switch (mode) { + case ArgumentsMode::Cloned: { + if (inlineCallFrame) { + if (inlineCallFrame->argumentCountRegister.isValid()) + length = targetFrame->r(inlineCallFrame->argumentCountRegister).unboxedInt32(); + else + length = inlineCallFrame->arguments.size(); + length--; + + for (unsigned i = length; i--;) + result->putDirectIndex(myFrame, i, inlineCallFrame->arguments[i + 1].recover(targetFrame)); + } else { + length = targetFrame->argumentCount(); + + for (unsigned i = length; i--;) + result->putDirectIndex(myFrame, i, targetFrame->uncheckedArgument(i)); + } + break; + } + + case ArgumentsMode::FakeValues: { + length = 0; + break; + } } + + result->putDirect(vm, vm.propertyNames->length, jsNumber(length), DontEnum); + + return result; +} + +ClonedArguments* ClonedArguments::createWithMachineFrame(ExecState* myFrame, ExecState* targetFrame, ArgumentsMode mode) +{ + return createWithInlineFrame(myFrame, targetFrame, nullptr, mode); +} + +ClonedArguments* ClonedArguments::createByCopyingFrom( + ExecState* exec, Structure* structure, Register* argumentStart, unsigned length, + JSFunction* callee) +{ + VM& vm = exec->vm(); + ClonedArguments* result = createEmpty(vm, structure, callee); + + for (unsigned i = length; i--;) + result->putDirectIndex(exec, i, argumentStart[i].jsValue()); + + result->putDirect(vm, vm.propertyNames->length, jsNumber(length), DontEnum); + return result; +} + +Structure* ClonedArguments::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) +{ + return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); +} + +bool ClonedArguments::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName ident, PropertySlot& slot) +{ + ClonedArguments* thisObject = jsCast(object); + VM& vm = exec->vm(); + + if (!thisObject->specialsMaterialized()) { + FunctionExecutable* executable = jsCast(thisObject->m_callee->executable()); + bool isStrictMode = executable->isStrictMode(); + + if (isStrictMode) { + if (ident == vm.propertyNames->callee) { + slot.setGetterSlot(thisObject, DontDelete | DontEnum | Accessor, thisObject->globalObject()->throwTypeErrorGetterSetter(vm)); + return true; + } + if (ident == vm.propertyNames->caller) { + slot.setGetterSlot(thisObject, DontDelete | DontEnum | Accessor, thisObject->globalObject()->throwTypeErrorGetterSetter(vm)); + return true; + } + + } else if (ident == vm.propertyNames->callee) { + slot.setValue(thisObject, 0, thisObject->m_callee.get()); + return true; + } + + if (ident == vm.propertyNames->iteratorSymbol) { + slot.setValue(thisObject, DontEnum, thisObject->globalObject()->arrayProtoValuesFunction()); + return true; + } + } + + return Base::getOwnPropertySlot(thisObject, exec, ident, slot); +} + +void ClonedArguments::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode) +{ + ClonedArguments* thisObject = jsCast(object); + thisObject->materializeSpecialsIfNecessary(exec); + Base::getOwnPropertyNames(thisObject, exec, array, mode); +} + +void ClonedArguments::put(JSCell* cell, ExecState* exec, PropertyName ident, JSValue value, PutPropertySlot& slot) +{ + ClonedArguments* thisObject = jsCast(cell); + VM& vm = exec->vm(); + + if (ident == vm.propertyNames->callee + || ident == vm.propertyNames->caller + || ident == vm.propertyNames->iteratorSymbol) { + thisObject->materializeSpecialsIfNecessary(exec); + PutPropertySlot dummy = slot; // Shadow the given PutPropertySlot to prevent caching. + Base::put(thisObject, exec, ident, value, dummy); + return; + } + + Base::put(thisObject, exec, ident, value, slot); +} + +bool ClonedArguments::deleteProperty(JSCell* cell, ExecState* exec, PropertyName ident) +{ + ClonedArguments* thisObject = jsCast(cell); + VM& vm = exec->vm(); + + if (ident == vm.propertyNames->callee + || ident == vm.propertyNames->caller + || ident == vm.propertyNames->iteratorSymbol) + thisObject->materializeSpecialsIfNecessary(exec); + + return Base::deleteProperty(thisObject, exec, ident); +} + +bool ClonedArguments::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName ident, const PropertyDescriptor& descriptor, bool shouldThrow) +{ + ClonedArguments* thisObject = jsCast(object); + VM& vm = exec->vm(); + + if (ident == vm.propertyNames->callee + || ident == vm.propertyNames->caller + || ident == vm.propertyNames->iteratorSymbol) + thisObject->materializeSpecialsIfNecessary(exec); + + return Base::defineOwnProperty(object, exec, ident, descriptor, shouldThrow); +} + +void ClonedArguments::materializeSpecials(ExecState* exec) +{ + RELEASE_ASSERT(!specialsMaterialized()); + VM& vm = exec->vm(); + + FunctionExecutable* executable = jsCast(m_callee->executable()); + bool isStrictMode = executable->isStrictMode(); + + if (isStrictMode) { + putDirectAccessor(exec, vm.propertyNames->callee, globalObject()->throwTypeErrorGetterSetter(vm), DontDelete | DontEnum | Accessor); + putDirectAccessor(exec, vm.propertyNames->caller, globalObject()->throwTypeErrorGetterSetter(vm), DontDelete | DontEnum | Accessor); + } else + putDirect(vm, vm.propertyNames->callee, JSValue(m_callee.get())); + + putDirect(vm, vm.propertyNames->iteratorSymbol, globalObject()->arrayProtoValuesFunction(), DontEnum); + + m_callee.clear(); +} + +void ClonedArguments::materializeSpecialsIfNecessary(ExecState* exec) +{ + if (!specialsMaterialized()) + materializeSpecials(exec); +} + +void ClonedArguments::visitChildren(JSCell* cell, SlotVisitor& visitor) +{ + ClonedArguments* thisObject = jsCast(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + visitor.append(&thisObject->m_callee); +} + +} // namespace JSC + diff --git a/Source/JavaScriptCore/runtime/ClonedArguments.h b/Source/JavaScriptCore/runtime/ClonedArguments.h new file mode 100644 index 000000000..8e713d5c6 --- /dev/null +++ b/Source/JavaScriptCore/runtime/ClonedArguments.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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. + */ + +#ifndef ClonedArguments_h +#define ClonedArguments_h + +#include "ArgumentsMode.h" +#include "JSObject.h" + +namespace JSC { + +// This is an Arguments-class object that we create when you do function.arguments, or you say +// "arguments" inside a function in strict mode. It behaves almpst entirely like an ordinary +// JavaScript object. All of the arguments values are simply copied from the stack (possibly via +// some sophisticated ValueRecovery's if an optimizing compiler is in play) and the appropriate +// properties of the object are populated. The only reason why we need a special class is to make +// the object claim to be "Arguments" from a toString standpoint, and to avoid materializing the +// caller/callee/@@iterator properties unless someone asks for them. +class ClonedArguments : public JSNonFinalObject { +public: + typedef JSNonFinalObject Base; + static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames; + +private: + ClonedArguments(VM&, Structure*); + +public: + static ClonedArguments* createEmpty(VM&, Structure*, JSFunction* callee); + static ClonedArguments* createEmpty(ExecState*, JSFunction* callee); + static ClonedArguments* createWithInlineFrame(ExecState* myFrame, ExecState* targetFrame, InlineCallFrame*, ArgumentsMode); + static ClonedArguments* createWithMachineFrame(ExecState* myFrame, ExecState* targetFrame, ArgumentsMode); + static ClonedArguments* createByCopyingFrom(ExecState*, Structure*, Register* argumentsStart, unsigned length, JSFunction* callee); + + static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype); + + static void visitChildren(JSCell*, SlotVisitor&); + + DECLARE_INFO; + +private: + static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); + static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); + static bool deleteProperty(JSCell*, ExecState*, PropertyName); + static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow); + + bool specialsMaterialized() const { return !m_callee; } + void materializeSpecials(ExecState*); + void materializeSpecialsIfNecessary(ExecState*); + + WriteBarrier m_callee; // Set to nullptr when we materialize all of our special properties. +}; + +} // namespace JSC + +#endif // ClonedArguments_h + diff --git a/Source/JavaScriptCore/runtime/CodeCache.cpp b/Source/JavaScriptCore/runtime/CodeCache.cpp index de904ae71..cd9caf7ff 100644 --- a/Source/JavaScriptCore/runtime/CodeCache.cpp +++ b/Source/JavaScriptCore/runtime/CodeCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Apple Inc. All Rights Reserved. + * Copyright (C) 2012, 2016 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,7 +29,7 @@ #include "BytecodeGenerator.h" #include "CodeSpecializationKind.h" -#include "Operations.h" +#include "JSCInlines.h" #include "Parser.h" #include "StrongInlines.h" #include "UnlinkedCodeBlock.h" @@ -37,11 +37,6 @@ namespace JSC { const double CodeCacheMap::workingSetTime = 10.0; -const int64_t CodeCacheMap::globalWorkingSetMaxBytes = 16000000; -const size_t CodeCacheMap::globalWorkingSetMaxEntries = 2000; -const unsigned CodeCacheMap::nonGlobalWorkingSetScale = 20; -const int64_t CodeCacheMap::nonGlobalWorkingSetMaxBytes = CodeCacheMap::globalWorkingSetMaxBytes / CodeCacheMap::nonGlobalWorkingSetScale; -const size_t CodeCacheMap::nonGlobalWorkingSetMaxEntries = CodeCacheMap::globalWorkingSetMaxEntries / CodeCacheMap::nonGlobalWorkingSetScale; void CodeCacheMap::pruneSlowCase() { @@ -59,9 +54,7 @@ void CodeCacheMap::pruneSlowCase() } } -CodeCache::CodeCache(CodeCacheKind kind) -: m_sourceCode(kind == GlobalCodeCache ? CodeCacheMap::globalWorkingSetMaxBytes : CodeCacheMap::nonGlobalWorkingSetMaxBytes, - kind == GlobalCodeCache ? CodeCacheMap::globalWorkingSetMaxEntries : CodeCacheMap::nonGlobalWorkingSetMaxEntries) +CodeCache::CodeCache() { } @@ -74,102 +67,134 @@ template struct CacheTypes { }; template <> struct CacheTypes { typedef JSC::ProgramNode RootNode; static const SourceCodeKey::CodeType codeType = SourceCodeKey::ProgramType; + static const SourceParseMode parseMode = SourceParseMode::ProgramMode; }; template <> struct CacheTypes { typedef JSC::EvalNode RootNode; static const SourceCodeKey::CodeType codeType = SourceCodeKey::EvalType; + static const SourceParseMode parseMode = SourceParseMode::ProgramMode; +}; + +template <> struct CacheTypes { + typedef JSC::ModuleProgramNode RootNode; + static const SourceCodeKey::CodeType codeType = SourceCodeKey::ModuleType; + static const SourceParseMode parseMode = SourceParseMode::ModuleEvaluateMode; }; template -UnlinkedCodeBlockType* CodeCache::generateBytecode(VM& vm, JSScope* scope, ExecutableType* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) +UnlinkedCodeBlockType* CodeCache::getGlobalCodeBlock(VM& vm, ExecutableType* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, ThisTDZMode thisTDZMode, bool, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error, const VariableEnvironment* variablesUnderTDZ) { + SourceCodeKey key = SourceCodeKey(source, String(), CacheTypes::codeType, builtinMode, strictMode, thisTDZMode); + SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key); + // FIXME: We should do something smart for TDZ instead of just disabling caching. + // https://bugs.webkit.org/show_bug.cgi?id=154010 + bool canCache = debuggerMode == DebuggerOff && profilerMode == ProfilerOff && !vm.typeProfiler() && !vm.controlFlowProfiler() && !variablesUnderTDZ->size(); + if (cache && canCache) { + UnlinkedCodeBlockType* unlinkedCodeBlock = jsCast(cache->cell.get()); + unsigned firstLine = source.firstLine() + unlinkedCodeBlock->firstLine(); + unsigned lineCount = unlinkedCodeBlock->lineCount(); + unsigned startColumn = unlinkedCodeBlock->startColumn() + source.startColumn(); + bool endColumnIsOnStartLine = !lineCount; + unsigned endColumn = unlinkedCodeBlock->endColumn() + (endColumnIsOnStartLine ? startColumn : 1); + executable->recordParse(unlinkedCodeBlock->codeFeatures(), unlinkedCodeBlock->hasCapturedVariables(), firstLine, firstLine + lineCount, startColumn, endColumn); + return unlinkedCodeBlock; + } + typedef typename CacheTypes::RootNode RootNode; - RefPtr rootNode = parse(&vm, source, 0, Identifier(), strictness, JSParseProgramCode, error); + std::unique_ptr rootNode = parse( + &vm, source, Identifier(), builtinMode, strictMode, + CacheTypes::parseMode, SuperBinding::NotNeeded, error, nullptr, ConstructorKind::None, thisTDZMode); if (!rootNode) - return 0; - executable->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo(), rootNode->lastLine(), rootNode->startColumn()); + return nullptr; - UnlinkedCodeBlockType* unlinkedCode = UnlinkedCodeBlockType::create(&vm, executable->executableInfo()); - unlinkedCode->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->lineNo() - source.firstLine(), rootNode->lastLine() - rootNode->lineNo()); - OwnPtr generator(adoptPtr(new BytecodeGenerator(vm, scope, rootNode.get(), unlinkedCode, debuggerMode, profilerMode))); - error = generator->generate(); - rootNode->destroyData(); - if (error.m_type != ParserError::ErrorNone) - return 0; - return unlinkedCode; -} + unsigned lineCount = rootNode->lastLine() - rootNode->firstLine(); + unsigned startColumn = rootNode->startColumn() + 1; + bool endColumnIsOnStartLine = !lineCount; + unsigned unlinkedEndColumn = rootNode->endColumn(); + unsigned endColumn = unlinkedEndColumn + (endColumnIsOnStartLine ? startColumn : 1); + unsigned arrowContextFeature = executable->isArrowFunctionContext() ? ArrowFunctionContextFeature : 0; + executable->recordParse(rootNode->features() | arrowContextFeature, rootNode->hasCapturedVariables(), rootNode->firstLine(), rootNode->lastLine(), startColumn, endColumn); -template -UnlinkedCodeBlockType* CodeCache::getCodeBlock(VM& vm, JSScope* scope, ExecutableType* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) -{ - // We completely skip the cache if we're an eval that isn't at the top of the scope chain. - if (CacheTypes::codeType == SourceCodeKey::EvalType) { - if (scope->next() && !scope->isActivationObject()) - return generateBytecode(vm, scope, executable, source, strictness, debuggerMode, profilerMode, error); - } + UnlinkedCodeBlockType* unlinkedCodeBlock = UnlinkedCodeBlockType::create(&vm, executable->executableInfo()); + unlinkedCodeBlock->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), rootNode->firstLine() - source.firstLine(), lineCount, unlinkedEndColumn); - SourceCodeKey key = SourceCodeKey(source, String(), CacheTypes::codeType, strictness); - CodeCacheMap::AddResult addResult = m_sourceCode.add(key, SourceCodeValue()); - bool canCache = debuggerMode == DebuggerOff && profilerMode == ProfilerOff; + auto generator = std::make_unique(vm, rootNode.get(), unlinkedCodeBlock, debuggerMode, profilerMode, variablesUnderTDZ); + error = generator->generate(); + if (error.isValid()) + return nullptr; - if (!addResult.isNewEntry && canCache) { - UnlinkedCodeBlockType* unlinkedCode = jsCast(addResult.iterator->value.cell.get()); - unsigned firstLine = source.firstLine() + unlinkedCode->firstLine(); - unsigned startColumn = source.firstLine() ? source.startColumn() : 0; - executable->recordParse(unlinkedCode->codeFeatures(), unlinkedCode->hasCapturedVariables(), firstLine, firstLine + unlinkedCode->lineCount(), startColumn); - return unlinkedCode; - } - UnlinkedCodeBlockType* unlinkedCode = generateBytecode(vm, scope, executable, source, strictness, debuggerMode, profilerMode, error); + if (!canCache) + return unlinkedCodeBlock; - if (!canCache || !unlinkedCode) { - m_sourceCode.remove(addResult.iterator); - return unlinkedCode; - } + m_sourceCode.addCache(key, SourceCodeValue(vm, unlinkedCodeBlock, m_sourceCode.age())); + return unlinkedCodeBlock; +} - addResult.iterator->value = SourceCodeValue(vm, unlinkedCode, m_sourceCode.age()); - return unlinkedCode; +UnlinkedProgramCodeBlock* CodeCache::getProgramCodeBlock(VM& vm, ProgramExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) +{ + VariableEnvironment emptyParentTDZVariables; + return getGlobalCodeBlock(vm, executable, source, builtinMode, strictMode, ThisTDZMode::CheckIfNeeded, false, debuggerMode, profilerMode, error, &emptyParentTDZVariables); } -UnlinkedProgramCodeBlock* CodeCache::getProgramCodeBlock(VM& vm, ProgramExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) +UnlinkedEvalCodeBlock* CodeCache::getEvalCodeBlock(VM& vm, EvalExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, JSParserStrictMode strictMode, ThisTDZMode thisTDZMode, bool isArrowFunctionContext, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error, const VariableEnvironment* variablesUnderTDZ) { - return getCodeBlock(vm, 0, executable, source, strictness, debuggerMode, profilerMode, error); + return getGlobalCodeBlock(vm, executable, source, builtinMode, strictMode, thisTDZMode, isArrowFunctionContext, debuggerMode, profilerMode, error, variablesUnderTDZ); } -UnlinkedEvalCodeBlock* CodeCache::getEvalCodeBlock(VM& vm, JSScope* scope, EvalExecutable* executable, const SourceCode& source, JSParserStrictness strictness, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) +UnlinkedModuleProgramCodeBlock* CodeCache::getModuleProgramCodeBlock(VM& vm, ModuleProgramExecutable* executable, const SourceCode& source, JSParserBuiltinMode builtinMode, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error) { - return getCodeBlock(vm, scope, executable, source, strictness, debuggerMode, profilerMode, error); + VariableEnvironment emptyParentTDZVariables; + return getGlobalCodeBlock(vm, executable, source, builtinMode, JSParserStrictMode::Strict, ThisTDZMode::CheckIfNeeded, false, debuggerMode, profilerMode, error, &emptyParentTDZVariables); } +// FIXME: There's no need to add the function's name to the key here. It's already in the source code. UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(VM& vm, const Identifier& name, const SourceCode& source, ParserError& error) { - SourceCodeKey key = SourceCodeKey(source, name.string(), SourceCodeKey::FunctionType, JSParseNormal); - CodeCacheMap::AddResult addResult = m_sourceCode.add(key, SourceCodeValue()); - if (!addResult.isNewEntry) - return jsCast(addResult.iterator->value.cell.get()); - - RefPtr program = parse(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error); + SourceCodeKey key = SourceCodeKey( + source, name.string(), SourceCodeKey::FunctionType, + JSParserBuiltinMode::NotBuiltin, + JSParserStrictMode::NotStrict); + SourceCodeValue* cache = m_sourceCode.findCacheAndUpdateAge(key); + if (cache) + return jsCast(cache->cell.get()); + + JSTextPosition positionBeforeLastNewline; + std::unique_ptr program = parse( + &vm, source, Identifier(), JSParserBuiltinMode::NotBuiltin, + JSParserStrictMode::NotStrict, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, + error, &positionBeforeLastNewline); if (!program) { - ASSERT(error.m_type != ParserError::ErrorNone); - m_sourceCode.remove(addResult.iterator); - return 0; + RELEASE_ASSERT(error.isValid()); + return nullptr; } - // This function assumes an input string that would result in a single anonymous function expression. - StatementNode* exprStatement = program->singleStatement(); - ASSERT(exprStatement); - ASSERT(exprStatement->isExprStatement()); - ExpressionNode* funcExpr = static_cast(exprStatement)->expr(); - ASSERT(funcExpr); - RELEASE_ASSERT(funcExpr->isFuncExprNode()); - FunctionBodyNode* body = static_cast(funcExpr)->body(); - ASSERT(body); - ASSERT(body->ident().isNull()); - - UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, body); + // This function assumes an input string that would result in a single function declaration. + StatementNode* statement = program->singleStatement(); + ASSERT(statement); + ASSERT(statement->isBlock()); + if (!statement || !statement->isBlock()) + return nullptr; + + StatementNode* funcDecl = static_cast(statement)->singleStatement(); + ASSERT(funcDecl); + ASSERT(funcDecl->isFuncDeclNode()); + if (!funcDecl || !funcDecl->isFuncDeclNode()) + return nullptr; + + FunctionMetadataNode* metadata = static_cast(funcDecl)->metadata(); + ASSERT(metadata); + if (!metadata) + return nullptr; + + metadata->setEndPosition(positionBeforeLastNewline); + // The Function constructor only has access to global variables, so no variables will be under TDZ. + VariableEnvironment emptyTDZVariables; + UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, UnlinkedNormalFunction, ConstructAbility::CanConstruct, emptyTDZVariables, DerivedContextType::None); + functionExecutable->m_nameValue.set(vm, functionExecutable, jsString(&vm, name.string())); - addResult.iterator->value = SourceCodeValue(vm, functionExecutable, m_sourceCode.age()); + m_sourceCode.addCache(key, SourceCodeValue(vm, functionExecutable, m_sourceCode.age())); return functionExecutable; } diff --git a/Source/JavaScriptCore/runtime/CodeCache.h b/Source/JavaScriptCore/runtime/CodeCache.h index 986b266c2..2132f0c19 100644 --- a/Source/JavaScriptCore/runtime/CodeCache.h +++ b/Source/JavaScriptCore/runtime/CodeCache.h @@ -29,92 +29,34 @@ #include "CodeSpecializationKind.h" #include "ParserModes.h" #include "SourceCode.h" +#include "SourceCodeKey.h" #include "Strong.h" -#include "WeakRandom.h" +#include "VariableEnvironment.h" #include -#include #include -#include #include +#include #include namespace JSC { class EvalExecutable; -class FunctionBodyNode; +class FunctionMetadataNode; class Identifier; class JSScope; +class ParserError; class ProgramExecutable; +class ModuleProgramExecutable; class UnlinkedCodeBlock; class UnlinkedEvalCodeBlock; +class UnlinkedModuleProgramCodeBlock; class UnlinkedFunctionCodeBlock; class UnlinkedFunctionExecutable; class UnlinkedProgramCodeBlock; class VM; -struct ParserError; class SourceCode; class SourceProvider; -class SourceCodeKey { -public: - enum CodeType { EvalType, ProgramType, FunctionType }; - - SourceCodeKey() - { - } - - SourceCodeKey(const SourceCode& sourceCode, const String& name, CodeType codeType, JSParserStrictness jsParserStrictness) - : m_sourceCode(sourceCode) - , m_name(name) - , m_flags((codeType << 1) | jsParserStrictness) - , m_hash(string().impl()->hash()) - { - } - - SourceCodeKey(WTF::HashTableDeletedValueType) - : m_sourceCode(WTF::HashTableDeletedValue) - { - } - - bool isHashTableDeletedValue() const { return m_sourceCode.isHashTableDeletedValue(); } - - unsigned hash() const { return m_hash; } - - size_t length() const { return m_sourceCode.length(); } - - bool isNull() const { return m_sourceCode.isNull(); } - - // To save memory, we compute our string on demand. It's expected that source - // providers cache their strings to make this efficient. - String string() const { return m_sourceCode.toString(); } - - bool operator==(const SourceCodeKey& other) const - { - return m_hash == other.m_hash - && length() == other.length() - && m_flags == other.m_flags - && m_name == other.m_name - && string() == other.string(); - } - -private: - SourceCode m_sourceCode; - String m_name; - unsigned m_flags; - unsigned m_hash; -}; - -struct SourceCodeKeyHash { - static unsigned hash(const SourceCodeKey& key) { return key.hash(); } - static bool equal(const SourceCodeKey& a, const SourceCodeKey& b) { return a == b; } - static const bool safeToCompareToEmptyOrDeleted = false; -}; - -struct SourceCodeKeyHashTraits : SimpleClassHashTraits { - static const bool hasIsEmptyValueFunction = true; - static bool isEmptyValue(const SourceCodeKey& sourceCodeKey) { return sourceCodeKey.isNull(); } -}; - struct SourceCodeValue { SourceCodeValue() { @@ -136,30 +78,25 @@ public: typedef MapType::iterator iterator; typedef MapType::AddResult AddResult; - CodeCacheMap(int64_t workingSetMaxBytes, size_t workingSetMaxEntries) + CodeCacheMap() : m_size(0) , m_sizeAtLastPrune(0) , m_timeAtLastPrune(monotonicallyIncreasingTime()) , m_minCapacity(0) , m_capacity(0) , m_age(0) - , m_workingSetMaxBytes(workingSetMaxBytes) - , m_workingSetMaxEntries(workingSetMaxEntries) { } - AddResult add(const SourceCodeKey& key, const SourceCodeValue& value) + SourceCodeValue* findCacheAndUpdateAge(const SourceCodeKey& key) { prune(); - AddResult addResult = m_map.add(key, value); - if (addResult.isNewEntry) { - m_size += key.length(); - m_age += key.length(); - return addResult; - } + iterator findResult = m_map.find(key); + if (findResult == m_map.end()) + return nullptr; - int64_t age = m_age - addResult.iterator->value.age; + int64_t age = m_age - findResult->value.age; if (age > m_capacity) { // A requested object is older than the cache's capacity. We can // infer that requested objects are subject to high eviction probability, @@ -174,7 +111,20 @@ public: m_capacity = m_minCapacity; } - addResult.iterator->value.age = m_age; + findResult->value.age = m_age; + m_age += key.length(); + + return &findResult->value; + } + + AddResult addCache(const SourceCodeKey& key, const SourceCodeValue& value) + { + prune(); + + AddResult addResult = m_map.add(key, value); + ASSERT(addResult.isNewEntry); + + m_size += key.length(); m_age += key.length(); return addResult; } @@ -194,20 +144,12 @@ public: int64_t age() { return m_age; } - static const int64_t globalWorkingSetMaxBytes; - static const size_t globalWorkingSetMaxEntries; - - // We have a smaller cap for the per-codeblock CodeCache that approximates the - // linked EvalCodeCache limits, but still allows us to keep large string based - // evals at least partially cached. - static const unsigned nonGlobalWorkingSetScale; - static const int64_t nonGlobalWorkingSetMaxBytes; - static const size_t nonGlobalWorkingSetMaxEntries; - private: // This constant factor biases cache capacity toward allowing a minimum // working set to enter the cache before it starts evicting. static const double workingSetTime; + static const int64_t workingSetMaxBytes = 16000000; + static const size_t workingSetMaxEntries = 2000; // This constant factor biases cache capacity toward recent activity. We // want to adapt to changing workloads. @@ -219,7 +161,7 @@ private: static const int64_t oldObjectSamplingMultiplier = 32; size_t numberOfEntries() const { return static_cast(m_map.size()); } - bool canPruneQuickly() const { return numberOfEntries() < m_workingSetMaxEntries; } + bool canPruneQuickly() const { return numberOfEntries() < workingSetMaxEntries; } void pruneSlowCase(); void prune() @@ -228,7 +170,7 @@ private: return; if (monotonicallyIncreasingTime() - m_timeAtLastPrune < workingSetTime - && m_size - m_sizeAtLastPrune < m_workingSetMaxBytes + && m_size - m_sizeAtLastPrune < workingSetMaxBytes && canPruneQuickly()) return; @@ -242,20 +184,19 @@ private: int64_t m_minCapacity; int64_t m_capacity; int64_t m_age; - const int64_t m_workingSetMaxBytes; - const size_t m_workingSetMaxEntries; }; // Caches top-level code such as