Make it possible to implement JS builtins in JS
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 31 Jan 2014 21:34:38 +0000 (21:34 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 31 Jan 2014 21:34:38 +0000 (21:34 +0000)
commitf07ffdc96fac8c4f8ac0a452edec4931ef9b597f
tree7d5c2e47b657c5f2ea418800262453125c304abe
parent2fc975638d5c59ae832e402dbab1ff58745e35f3
Make it possible to implement JS builtins in JS
https://bugs.webkit.org/show_bug.cgi?id=127887

Reviewed by Michael Saboff.

.:

CMake updates

* Source/cmake/gtest/CMakeLists.txt:

Source/JavaScriptCore:

This patch makes it possible to write builtin functions in JS.
The bindings, generators, and definitions are all created automatically
based on js files in the builtins/ directory.  This patch includes one
such case: Array.prototype.js with an implementation of every().

There's a lot of refactoring to make it possible for CommonIdentifiers
to include the output of the generated files (DerivedSources/JSCBuiltins.{h,cpp})
without breaking the offset extractor. The result of this refactoring
is that CommonIdentifiers, and a few other miscellaneous headers now
need to be included directly as they were formerly captured through other
paths.

In addition this adds a flag to the Lookup table's hashentry to indicate
that a static function is actually backed by JS. There is then a lot of
logic to thread the special nature of the functon to where it matters.
This allows toString(), .caller, etc to mimic the behaviour of a host
function.

Notes on writing builtins:
 - Each function is compiled independently of the others, and those
   implementations cannot currently capture all global properties (as
   that could be potentially unsafe). If a function does capture a
   global we will deliberately crash.
 - For those "global" properties that we do want access to, we use
   the @ prefix, e.g. Object(this) becomes @Object(this). The @ identifiers
   are private names, and behave just like regular properties, only
   without the risk of adulteration. Again, in the @Object case, we
   explicitly duplicate the ObjectConstructor reference on the GlobalObject
   so that we have guaranteed access to the original version of the
   constructor.
 - call, apply, eval, and Function are all rejected identifiers, again
   to prevent anything from accidentally using an adulterated object.
   Instead @call and @apply are available, and happily they completely
   drop the neq_ptr instruction as they're defined as always being the
   original call/apply functions.

These restrictions are just intended to make it harder to accidentally
make changes that are incorrect (for instance calling whatever has been
assigned to global.Object, instead of the original constructor function).
However, making a mistake like this should result in a purely semantic
error as fundamentally these functions are treated as though they were
regular JS code in the host global, and have no more privileges than
any other JS.

The initial proof of concept is Array.prototype.every, this shows a 65%
performance improvement, and that improvement is significantly hurt by
our poor optimisation of op_in.

As this is such a limited function, we have not yet exported all symbols
that we could possibly need, but as we implement more, the likelihood
of encountering missing features will reduce.

This did require breaking out a JSStringInlines header, and required
fixing a few objects that were trying to using PropertyName::publicName
rather than PropertyName::uid.

* API/JSCallbackObjectFunctions.h:
(JSC::JSCallbackObject<Parent>::getOwnPropertySlot):
(JSC::JSCallbackObject<Parent>::put):
(JSC::JSCallbackObject<Parent>::deleteProperty):
(JSC::JSCallbackObject<Parent>::getStaticValue):
(JSC::JSCallbackObject<Parent>::staticFunctionGetter):
(JSC::JSCallbackObject<Parent>::callbackGetter):
* CMakeLists.txt:
* DerivedSources.make:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* builtins/Array.prototype.js:
(every):
* builtins/BuiltinExecutables.cpp: Added.
(JSC::BuiltinExecutables::BuiltinExecutables):
(JSC::BuiltinExecutables::createBuiltinExecutable):
* builtins/BuiltinExecutables.h:
(JSC::BuiltinExecutables::create):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock):
* bytecode/CodeBlock.h:
* bytecode/ProfiledCodeBlockJettisoningWatchpoint.cpp:
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::generateFunctionCodeBlock):
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
(JSC::UnlinkedFunctionExecutable::codeBlockFor):
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
* bytecode/UnlinkedCodeBlock.h:
(JSC::ExecutableInfo::ExecutableInfo):
(JSC::UnlinkedFunctionExecutable::create):
(JSC::UnlinkedFunctionExecutable::toStrictness):
(JSC::UnlinkedFunctionExecutable::isBuiltinFunction):
(JSC::UnlinkedCodeBlock::isBuiltinFunction):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::isBuiltinFunction):
(JSC::BytecodeGenerator::makeFunction):
* bytecompiler/NodesCodegen.cpp:
(JSC::CallFunctionCallDotNode::emitBytecode):
(JSC::ApplyFunctionCallDotNode::emitBytecode):
* create_hash_table:
* dfg/DFGOperations.cpp:
* generate-js-builtins: Added.
(getCopyright):
(getFunctions):
(generateCode):
(mangleName):
(FunctionExecutable):
(Identifier):
(JSGlobalObject):
(SourceCode):
(UnlinkedFunctionExecutable):
(VM):
* interpreter/Interpreter.cpp:
* interpreter/ProtoCallFrame.cpp:
* jit/JITOpcodes.cpp:
* jit/JITOpcodes32_64.cpp:
* jit/JITOperations.cpp:
* jit/JITPropertyAccess.cpp:
* jit/JITPropertyAccess32_64.cpp:
* jsc.cpp:
* llint/LLIntSlowPaths.cpp:
* parser/ASTBuilder.h:
(JSC::ASTBuilder::makeFunctionCallNode):
* parser/Lexer.cpp:
(JSC::Lexer<T>::Lexer):
(JSC::isSafeIdentifier):
(JSC::Lexer<LChar>::parseIdentifier):
(JSC::Lexer<UChar>::parseIdentifier):
(JSC::Lexer<T>::lex):
* parser/Lexer.h:
(JSC::isSafeIdentifier):
(JSC::Lexer<T>::lexExpectIdentifier):
* parser/Nodes.cpp:
(JSC::ProgramNode::setClosedVariables):
* parser/Nodes.h:
(JSC::ScopeNode::capturedVariables):
(JSC::ScopeNode::setClosedVariables):
(JSC::ProgramNode::closedVariables):
* parser/Parser.cpp:
(JSC::Parser<LexerType>::Parser):
(JSC::Parser<LexerType>::parseInner):
(JSC::Parser<LexerType>::didFinishParsing):
(JSC::Parser<LexerType>::printUnexpectedTokenText):
* parser/Parser.h:
(JSC::Scope::getUsedVariables):
(JSC::Parser::closedVariables):
(JSC::parse):
* parser/ParserModes.h:
* parser/ParserTokens.h:
* runtime/ArgList.cpp:
* runtime/Arguments.cpp:
* runtime/Arguments.h:
* runtime/ArgumentsIteratorConstructor.cpp:
* runtime/ArgumentsIteratorPrototype.cpp:
* runtime/ArrayPrototype.cpp:
* runtime/CodeCache.cpp:
(JSC::CodeCache::getFunctionExecutableFromGlobalCode):
* runtime/CommonIdentifiers.cpp:
(JSC::CommonIdentifiers::CommonIdentifiers):
(JSC::CommonIdentifiers::getPrivateName):
(JSC::CommonIdentifiers::getPublicName):
* runtime/CommonIdentifiers.h:
* runtime/CommonSlowPaths.cpp:
* runtime/CommonSlowPathsExceptions.cpp:
* runtime/ExceptionHelpers.cpp:
(JSC::createUndefinedVariableError):
* runtime/Executable.h:
(JSC::EvalExecutable::executableInfo):
(JSC::ProgramExecutable::executableInfo):
(JSC::FunctionExecutable::isBuiltinFunction):
* runtime/FunctionPrototype.cpp:
(JSC::functionProtoFuncToString):
* runtime/JSActivation.cpp:
(JSC::JSActivation::symbolTableGet):
(JSC::JSActivation::symbolTablePut):
(JSC::JSActivation::symbolTablePutWithAttributes):
* runtime/JSArgumentsIterator.cpp:
* runtime/JSArray.cpp:
* runtime/JSArrayIterator.cpp:
* runtime/JSCJSValue.cpp:
* runtime/JSCellInlines.h:
* runtime/JSFunction.cpp:
(JSC::JSFunction::createBuiltinFunction):
(JSC::JSFunction::calculatedDisplayName):
(JSC::JSFunction::sourceCode):
(JSC::JSFunction::isHostOrBuiltinFunction):
(JSC::JSFunction::isBuiltinFunction):
(JSC::JSFunction::callerGetter):
(JSC::JSFunction::getOwnPropertySlot):
(JSC::JSFunction::getOwnNonIndexPropertyNames):
(JSC::JSFunction::put):
(JSC::JSFunction::defineOwnProperty):
* runtime/JSFunction.h:
* runtime/JSGenericTypedArrayViewConstructorInlines.h:
* runtime/JSGenericTypedArrayViewInlines.h:
* runtime/JSGenericTypedArrayViewPrototypeInlines.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::reset):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::objectConstructor):
(JSC::JSGlobalObject::symbolTableHasProperty):
* runtime/JSObject.cpp:
(JSC::getClassPropertyNames):
(JSC::JSObject::reifyStaticFunctionsForDelete):
(JSC::JSObject::putDirectBuiltinFunction):
* runtime/JSObject.h:
* runtime/JSPropertyNameIterator.cpp:
* runtime/JSPropertyNameIterator.h:
* runtime/JSString.h:
* runtime/JSStringInlines.h: Added.
(JSC::JSString::getStringPropertySlot):
(JSC::inlineJSValueNotStringtoString):
(JSC::JSValue::toWTFStringInline):
* runtime/JSSymbolTableObject.cpp:
(JSC::JSSymbolTableObject::getOwnNonIndexPropertyNames):
   Don't report private names.
* runtime/JSSymbolTableObject.h:
(JSC::symbolTableGet):
(JSC::symbolTablePut):
(JSC::symbolTablePutWithAttributes):
* runtime/Lookup.cpp:
(JSC::setUpStaticFunctionSlot):
* runtime/Lookup.h:
(JSC::HashEntry::builtinGenerator):
(JSC::HashEntry::propertyGetter):
(JSC::HashEntry::propertyPutter):
(JSC::HashTable::entry):
(JSC::getStaticPropertySlot):
(JSC::getStaticValueSlot):
(JSC::putEntry):
* runtime/NativeErrorConstructor.cpp:
(JSC::NativeErrorConstructor::finishCreation):
* runtime/NativeErrorConstructor.h:
* runtime/PropertySlot.h:
* runtime/RegExpPrototype.cpp:
* runtime/SetConstructor.cpp:
* runtime/StringObject.cpp:
* runtime/Structure.cpp:
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:
(JSC::VM::builtinExecutables):

Source/WebCore:

Updating for the newly required headers.

Test: js/regress/array-prototype-every.html

* ForwardingHeaders/runtime/JSStringInlines.h: Added.
* Modules/plugins/QuickTimePluginReplacement.cpp:
* bindings/js/JSIDBAnyCustom.cpp:
* bindings/js/JSIDBDatabaseCustom.cpp:
* bindings/js/JSIDBObjectStoreCustom.cpp:

Source/WebKit:

CMake updates

* CMakeLists.txt:

Source/WebKit2:

CMake updates

* CMakeLists.txt:

Tools:

CMake updates

* DumpRenderTree/CMakeLists.txt:
* WebKitTestRunner/CMakeLists.txt:
* WinCELauncher/CMakeLists.txt:

LayoutTests:

Updated the test results for new error messages (now that they're
actually helpful), and added a js-regress test to track performance.

* js/array-every-expected.txt:
* js/dom/array-prototype-properties-expected.txt:
* js/regress/array-prototype-every-expected.txt: Added.
* js/regress/array-prototype-every.html: Added.
* js/regress/script-tests/array-prototype-every.js: Added.
(test1):
(test2):
(test3):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@163195 268f45cc-cd09-0410-ab3c-d52691b4dbfc
120 files changed:
ChangeLog
GNUmakefile.am
LayoutTests/ChangeLog
LayoutTests/js/array-every-expected.txt
LayoutTests/js/dom/array-prototype-properties-expected.txt
LayoutTests/js/regress/array-prototype-every-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/array-prototype-every.html [new file with mode: 0644]
LayoutTests/js/regress/script-tests/array-prototype-every.js [new file with mode: 0644]
Source/JavaScriptCore/API/JSCallbackObjectFunctions.h
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/DerivedSources.make
Source/JavaScriptCore/GNUmakefile.am
Source/JavaScriptCore/GNUmakefile.list.am
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCoreCommon.props
Source/JavaScriptCore/JavaScriptCore.vcxproj/copy-files.cmd
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/builtins/Array.prototype.js [new file with mode: 0644]
Source/JavaScriptCore/builtins/BuiltinExecutables.cpp [new file with mode: 0644]
Source/JavaScriptCore/builtins/BuiltinExecutables.h [new file with mode: 0644]
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/ProfiledCodeBlockJettisoningWatchpoint.cpp
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/create_hash_table
Source/JavaScriptCore/dfg/DFGDominators.cpp
Source/JavaScriptCore/dfg/DFGJITCode.cpp
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/generate-js-builtins [new file with mode: 0644]
Source/JavaScriptCore/interpreter/CachedCall.h
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/interpreter/ProtoCallFrame.cpp
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/jit/JITPropertyAccess.cpp
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/parser/ASTBuilder.h
Source/JavaScriptCore/parser/Lexer.cpp
Source/JavaScriptCore/parser/Lexer.h
Source/JavaScriptCore/parser/Nodes.cpp
Source/JavaScriptCore/parser/Nodes.h
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/parser/ParserModes.h
Source/JavaScriptCore/parser/ParserTokens.h
Source/JavaScriptCore/runtime/Arguments.h
Source/JavaScriptCore/runtime/ArgumentsIteratorPrototype.cpp
Source/JavaScriptCore/runtime/ArrayPrototype.cpp
Source/JavaScriptCore/runtime/CodeCache.cpp
Source/JavaScriptCore/runtime/CommonIdentifiers.cpp
Source/JavaScriptCore/runtime/CommonIdentifiers.h
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/CommonSlowPathsExceptions.cpp
Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/FunctionPrototype.cpp
Source/JavaScriptCore/runtime/JSActivation.cpp
Source/JavaScriptCore/runtime/JSArgumentsIterator.cpp
Source/JavaScriptCore/runtime/JSArray.cpp
Source/JavaScriptCore/runtime/JSArrayIterator.cpp
Source/JavaScriptCore/runtime/JSCJSValue.cpp
Source/JavaScriptCore/runtime/JSCellInlines.h
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSFunction.h
Source/JavaScriptCore/runtime/JSFunctionInlines.h
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeInlines.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp
Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp
Source/JavaScriptCore/runtime/JSPromisePrototype.cpp
Source/JavaScriptCore/runtime/JSPromiseReaction.h
Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
Source/JavaScriptCore/runtime/JSString.h
Source/JavaScriptCore/runtime/JSStringInlines.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp
Source/JavaScriptCore/runtime/JSSymbolTableObject.h
Source/JavaScriptCore/runtime/Lookup.cpp
Source/JavaScriptCore/runtime/Lookup.h
Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
Source/JavaScriptCore/runtime/NativeErrorConstructor.h
Source/JavaScriptCore/runtime/PropertySlot.h
Source/JavaScriptCore/runtime/RegExpConstructor.cpp
Source/JavaScriptCore/runtime/RegExpPrototype.cpp
Source/JavaScriptCore/runtime/SetConstructor.cpp
Source/JavaScriptCore/runtime/StringObject.cpp
Source/JavaScriptCore/runtime/Structure.cpp
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/ForwardingHeaders/runtime/JSStringInlines.h [new file with mode: 0644]
Source/WebCore/Modules/plugins/QuickTimePluginReplacement.cpp
Source/WebCore/bindings/js/JSIDBAnyCustom.cpp
Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp
Source/WebCore/bindings/js/JSIDBObjectStoreCustom.cpp
Source/WebCore/bindings/js/JSNodeFilterCondition.cpp
Source/WebKit/CMakeLists.txt
Source/WebKit/ChangeLog
Source/WebKit2/CMakeLists.txt
Source/WebKit2/ChangeLog
Source/cmake/gtest/CMakeLists.txt
Tools/ChangeLog
Tools/DumpRenderTree/CMakeLists.txt
Tools/WebKitTestRunner/CMakeLists.txt
Tools/WinCELauncher/CMakeLists.txt