Make it possible to implement JS builtins in JS
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Feb 2014 17:14:23 +0000 (17:14 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Feb 2014 17:14:23 +0000 (17:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=127887

Reviewed by Michael Saboff.

.:

* GNUmakefile.am:
* 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.

* 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.am:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.vcxproj/JavaScriptCoreCommon.props:
* JavaScriptCore.vcxproj/copy-files.cmd:
* 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):
* builtins/BuiltinNames.h: Added.
(JSC::BuiltinNames::BuiltinNames):
(JSC::BuiltinNames::getPrivateName):
(JSC::BuiltinNames::getPublicName):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::CodeBlock):
* 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:
* generate-js-builtins: Added.
(getCopyright):
(getFunctions):
(generateCode):
(mangleName):
(FunctionExecutable):
(Identifier):
(JSGlobalObject):
(SourceCode):
(UnlinkedFunctionExecutable):
(VM):
* interpreter/CachedCall.h:
(JSC::CachedCall::CachedCall):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::makeFunctionCallNode):
* parser/Lexer.cpp:
(JSC::Lexer<T>::Lexer):
(JSC::isSafeBuiltinIdentifier):
(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/ArrayPrototype.cpp:
* runtime/CodeCache.cpp:
(JSC::CodeCache::getFunctionExecutableFromGlobalCode):
* runtime/CommonIdentifiers.cpp:
(JSC::CommonIdentifiers::CommonIdentifiers):
(JSC::CommonIdentifiers::~CommonIdentifiers):
(JSC::CommonIdentifiers::getPrivateName):
(JSC::CommonIdentifiers::getPublicName):
* runtime/CommonIdentifiers.h:
(JSC::CommonIdentifiers::builtinNames):
* 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/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/JSFunctionInlines.h:
(JSC::JSFunction::nativeFunction):
(JSC::JSFunction::nativeConstructor):
(JSC::isHostFunction):
* 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/JSSymbolTableObject.cpp:
(JSC::JSSymbolTableObject::getOwnNonIndexPropertyNames):
* 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/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:
(JSC::VM::builtinExecutables):

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@163960 268f45cc-cd09-0410-ab3c-d52691b4dbfc

70 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/builtins/BuiltinNames.h [new file with mode: 0644]
Source/JavaScriptCore/bytecode/CodeBlock.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/generate-js-builtins [new file with mode: 0644]
Source/JavaScriptCore/interpreter/CachedCall.h
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/ArrayPrototype.cpp
Source/JavaScriptCore/runtime/CodeCache.cpp
Source/JavaScriptCore/runtime/CommonIdentifiers.cpp
Source/JavaScriptCore/runtime/CommonIdentifiers.h
Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/FunctionPrototype.cpp
Source/JavaScriptCore/runtime/JSActivation.cpp
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSFunction.h
Source/JavaScriptCore/runtime/JSFunctionInlines.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObject.h
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/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/cmake/gtest/CMakeLists.txt
Tools/ChangeLog
Tools/DumpRenderTree/CMakeLists.txt
Tools/WebKitTestRunner/CMakeLists.txt
Tools/WinCELauncher/CMakeLists.txt

index 342ee3e..099cd65 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2014-02-11  Oliver Hunt  <oliver@apple.com>
+
+        Make it possible to implement JS builtins in JS
+        https://bugs.webkit.org/show_bug.cgi?id=127887
+
+        Reviewed by Michael Saboff.
+
+        * GNUmakefile.am:
+        * Source/cmake/gtest/CMakeLists.txt:
+
 2014-02-12  Ryan Lortie  <desrt@desrt.ca>
 
         'ar T' is not portable and breaks the build on FreeBSD
index 73fc492..08c9115 100644 (file)
@@ -68,6 +68,7 @@ ALL_MOFILES :=
 dom_binding_idls :=
 wtf_sources :=
 javascriptcore_h_api :=
+javascriptcore_builtins_js_nosources :=
 javascriptcore_cppflags:=
 javascriptcore_cflags :=
 javascriptcore_sources :=
index f3b1f5e..7be8436 100644 (file)
@@ -1,3 +1,22 @@
+2014-02-11  Oliver Hunt  <oliver@apple.com>
+
+        Make it possible to implement JS builtins in JS
+        https://bugs.webkit.org/show_bug.cgi?id=127887
+
+        Reviewed by Michael Saboff.
+
+        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):
+
 2014-02-12  Raphael Kubo da Costa  <raphael.kubo.da.costa@intel.com>
 
         Update the HTML Media Capture implementation.
index 541b8c3..cca363d 100644 (file)
@@ -30,12 +30,12 @@ PASS [12, 5, 8, 130, 44].every(isBigEnoughAndException) threw exception exceptio
 PASS [12, 54, 18, 130, 44].every(isBigEnoughAndException) threw exception exception from function.
 
 5.0 Wrong Type for Callback Test
-PASS [12, 5, 8, 130, 44].every(5) threw exception TypeError: Type error.
-PASS [12, 5, 8, 130, 44].every('wrong') threw exception TypeError: Type error.
-PASS [12, 5, 8, 130, 44].every(new Object()) threw exception TypeError: Type error.
-PASS [12, 5, 8, 130, 44].every(null) threw exception TypeError: Type error.
-PASS [12, 5, 8, 130, 44].every(undefined) threw exception TypeError: Type error.
-PASS [12, 5, 8, 130, 44].every() threw exception TypeError: Type error.
+PASS [12, 5, 8, 130, 44].every(5) threw exception TypeError: Array.prototype.every callback must be a function.
+PASS [12, 5, 8, 130, 44].every('wrong') threw exception TypeError: Array.prototype.every callback must be a function.
+PASS [12, 5, 8, 130, 44].every(new Object()) threw exception TypeError: Array.prototype.every callback must be a function.
+PASS [12, 5, 8, 130, 44].every(null) threw exception TypeError: Array.prototype.every callback must be a function.
+PASS [12, 5, 8, 130, 44].every(undefined) threw exception TypeError: Array.prototype.every callback must be a function.
+PASS [12, 5, 8, 130, 44].every() threw exception TypeError: Array.prototype.every callback must be a function.
 
 6.0 Early Exit ("Short Circuiting")
 PASS [12, 5, 8, 130, 44].every(isBigEnoughShortCircuit) is false
index 2c2a68c..5d9ecb7 100644 (file)
@@ -15,7 +15,7 @@ PASS Array.prototype.slice.call(undefined, 0, 1) threw exception TypeError: unde
 PASS Array.prototype.sort.call(undefined) threw exception TypeError: undefined is not an object (evaluating 'Array.prototype.sort.call(undefined)').
 PASS Array.prototype.splice.call(undefined, 0, 1) threw exception TypeError: undefined is not an object (evaluating 'Array.prototype.splice.call(undefined, 0, 1)').
 PASS Array.prototype.unshift.call(undefined, {}) threw exception TypeError: undefined is not an object (evaluating 'Array.prototype.unshift.call(undefined, {})').
-PASS Array.prototype.every.call(undefined, toString) threw exception TypeError: undefined is not an object (evaluating 'Array.prototype.every.call(undefined, toString)').
+PASS Array.prototype.every.call(undefined, toString) threw exception TypeError: Array.prototype.every requires that |this| not be undefined.
 PASS Array.prototype.forEach.call(undefined, toString) threw exception TypeError: undefined is not an object (evaluating 'Array.prototype.forEach.call(undefined, toString)').
 PASS Array.prototype.some.call(undefined, toString) threw exception TypeError: undefined is not an object (evaluating 'Array.prototype.some.call(undefined, toString)').
 PASS Array.prototype.indexOf.call(undefined, 0) threw exception TypeError: undefined is not an object (evaluating 'Array.prototype.indexOf.call(undefined, 0)').
diff --git a/LayoutTests/js/regress/array-prototype-every-expected.txt b/LayoutTests/js/regress/array-prototype-every-expected.txt
new file mode 100644 (file)
index 0000000..1290c0e
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/array-prototype-every
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/array-prototype-every.html b/LayoutTests/js/regress/array-prototype-every.html
new file mode 100644 (file)
index 0000000..6e5cc17
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="resources/regress-pre.js"></script>
+<script src="script-tests/array-prototype-every.js"></script>
+<script src="resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/script-tests/array-prototype-every.js b/LayoutTests/js/regress/script-tests/array-prototype-every.js
new file mode 100644 (file)
index 0000000..294aa16
--- /dev/null
@@ -0,0 +1,29 @@
+var result = 0;
+function test1(a) {
+    result << 1;
+    result++;
+    return true;
+}
+function test2(a,b) {
+    result ^= 3;
+    result *= 3;
+    return true;
+}
+function test3(a,b,c) {
+    result ^= result >> 1;
+    return true;
+}
+
+var result = 0;
+var array = []
+for (var i = 0; i < 100000; ++i)
+    array[i] = 1;
+
+for (var i = 0; i < 10; i++) {
+    array.every(test1);
+    array.every(test2);
+    array.every(test3);
+}
+
+if (result != 1428810496)
+    throw "Error: bad result: " + result;
index 0ebe7dd..5c05bf1 100644 (file)
@@ -136,7 +136,7 @@ bool JSCallbackObject<Parent>::getOwnPropertySlot(JSObject* object, ExecState* e
     JSObjectRef thisRef = toRef(thisObject);
     RefPtr<OpaqueJSString> propertyNameRef;
     
-    if (StringImpl* name = propertyName.publicName()) {
+    if (StringImpl* name = propertyName.uid()) {
         for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
             // optional optimization to bypass getProperty in cases when we only need to know if the property exists
             if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) {
@@ -228,7 +228,7 @@ void JSCallbackObject<Parent>::put(JSCell* cell, ExecState* exec, PropertyName p
     RefPtr<OpaqueJSString> propertyNameRef;
     JSValueRef valueRef = toRef(exec, value);
     
-    if (StringImpl* name = propertyName.publicName()) {
+    if (StringImpl* name = propertyName.uid()) {
         for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
             if (JSObjectSetPropertyCallback setProperty = jsClass->setProperty) {
                 if (!propertyNameRef)
@@ -343,7 +343,7 @@ bool JSCallbackObject<Parent>::deleteProperty(JSCell* cell, ExecState* exec, Pro
     JSObjectRef thisRef = toRef(thisObject);
     RefPtr<OpaqueJSString> propertyNameRef;
     
-    if (StringImpl* name = propertyName.publicName()) {
+    if (StringImpl* name = propertyName.uid()) {
         for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) {
             if (JSObjectDeletePropertyCallback deleteProperty = jsClass->deleteProperty) {
                 if (!propertyNameRef)
@@ -564,7 +564,7 @@ JSValue JSCallbackObject<Parent>::getStaticValue(ExecState* exec, PropertyName p
 {
     JSObjectRef thisRef = toRef(this);
     
-    if (StringImpl* name = propertyName.publicName()) {
+    if (StringImpl* name = propertyName.uid()) {
         for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) {
             if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
                 if (StaticValueEntry* entry = staticValues->get(name)) {
@@ -600,7 +600,7 @@ EncodedJSValue JSCallbackObject<Parent>::staticFunctionGetter(ExecState* exec, J
     if (Parent::getOwnPropertySlot(thisObj, exec, propertyName, slot2))
         return JSValue::encode(slot2.getValue(exec, propertyName));
 
-    if (StringImpl* name = propertyName.publicName()) {
+    if (StringImpl* name = propertyName.uid()) {
         for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass) {
             if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
                 if (StaticFunctionEntry* entry = staticFunctions->get(name)) {
@@ -626,7 +626,7 @@ EncodedJSValue JSCallbackObject<Parent>::callbackGetter(ExecState* exec, JSObjec
     JSObjectRef thisRef = toRef(thisObj);
     RefPtr<OpaqueJSString> propertyNameRef;
     
-    if (StringImpl* name = propertyName.publicName()) {
+    if (StringImpl* name = propertyName.uid()) {
         for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass) {
             if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
                 if (!propertyNameRef)
index 969d6be..ea216e2 100644 (file)
@@ -5,6 +5,7 @@ set(JavaScriptCore_INCLUDE_DIRECTORIES
     "${JAVASCRIPTCORE_DIR}/ForwardingHeaders"
     "${JAVASCRIPTCORE_DIR}/assembler"
     "${JAVASCRIPTCORE_DIR}/bindings"
+    "${JAVASCRIPTCORE_DIR}/builtins"
     "${JAVASCRIPTCORE_DIR}/bytecode"
     "${JAVASCRIPTCORE_DIR}/bytecompiler"
     "${JAVASCRIPTCORE_DIR}/dfg"
@@ -52,6 +53,8 @@ set(JavaScriptCore_SOURCES
     bindings/ScriptObject.cpp
     bindings/ScriptValue.cpp
 
+    builtins/BuiltinExecutables.cpp
+
     bytecode/ArrayAllocationProfile.cpp
     bytecode/ArrayProfile.cpp
     bytecode/BytecodeBasicBlock.cpp
@@ -719,7 +722,7 @@ set(HASH_LUT_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/create_hash_table)
 macro(GENERATE_HASH_LUT _input _output)
     add_custom_command(
         OUTPUT ${_output}
-        DEPENDS ${HASH_LUT_GENERATOR} ${_input}
+        DEPENDS ${HASH_LUT_GENERATOR} ${_input} ${CMAKE_CURRENT_SOURCE_DIR}/generate-js-builtins
         COMMAND ${PERL_EXECUTABLE} ${HASH_LUT_GENERATOR} ${_input} -i > ${_output}
         VERBATIM)
     list(APPEND JavaScriptCore_HEADERS ${_output})
@@ -748,6 +751,7 @@ set(JavaScriptCore_FORWARDING_HEADERS_DIRECTORIES
     yarr
 
     collector/handles
+    ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}
 )
 
 set(JavaScriptCore_FORWARDING_HEADERS_FILES
@@ -775,8 +779,11 @@ set(JavaScriptCore_FORWARDING_HEADERS_FILES
     assembler/LinkBuffer.h
     assembler/MacroAssembler.h
     assembler/MacroAssemblerCodeRef.h
+    assembler/MacroAssemblerCodeRef.h
     jit/GPRInfo.h
     runtime/VM.h
+
+    ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/JSCBuiltins.h
 )
 
 
@@ -828,16 +835,27 @@ add_custom_command(
     COMMAND ${PYTHON_EXECUTABLE} ${JavaScriptCore_INSPECTOR_SCRIPTS_DIR}/CodeGeneratorInspector.py ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/InspectorJS.json --output_h_dir "${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}" --output_cpp_dir "${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}" --output_js_dir "${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}" --output_type JavaScript --write_always && mkdir -p ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/inspector && cp ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/InspectorJSBackendDispatchers.h ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/InspectorJSFrontendDispatchers.h ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/InspectorJSTypeBuilders.h ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/inspector
     VERBATIM)
 
+# JSCBuiltins
+file(GLOB JSCBuiltins_js_files "${CMAKE_CURRENT_SOURCE_DIR}/builtins/*.js")
+add_custom_command(
+   OUTPUT ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/JSCBuiltins.cpp ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/JSCBuiltins.h
+   MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/generate-js-builtins
+   DEPENDS ${JSCBuiltins_js_files}
+   COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/generate-js-builtins ${JSCBuiltins_js_files} ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/JSCBuiltins.h ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/JSCBuiltins.cpp
+   VERBATIM)
+
 list(APPEND JavaScriptCore_SOURCES
     ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/InspectorJSBackendDispatchers.cpp
     ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/InspectorJSFrontendDispatchers.cpp
     ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/InspectorJSTypeBuilders.cpp
+    ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/JSCBuiltins.cpp
 )
 
 list(APPEND JavaScriptCore_HEADERS
     ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/InspectorJSBackendDispatchers.h
     ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/InspectorJSFrontendDispatchers.h
     ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/InspectorJSTypeBuilders.h
+    ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/JSCBuiltins.h
 )
 
 add_custom_command(
index 1404284..254b112 100644 (file)
@@ -1,3 +1,227 @@
+2014-02-11  Oliver Hunt  <oliver@apple.com>
+
+        Make it possible to implement JS builtins in JS
+        https://bugs.webkit.org/show_bug.cgi?id=127887
+
+        Reviewed by Michael Saboff.
+
+        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.
+
+
+        * 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.am:
+        * GNUmakefile.list.am:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+        * JavaScriptCore.vcxproj/JavaScriptCoreCommon.props:
+        * JavaScriptCore.vcxproj/copy-files.cmd:
+        * 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):
+        * builtins/BuiltinNames.h: Added.
+        (JSC::BuiltinNames::BuiltinNames):
+        (JSC::BuiltinNames::getPrivateName):
+        (JSC::BuiltinNames::getPublicName):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::CodeBlock):
+        * 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:
+        * generate-js-builtins: Added.
+        (getCopyright):
+        (getFunctions):
+        (generateCode):
+        (mangleName):
+        (FunctionExecutable):
+        (Identifier):
+        (JSGlobalObject):
+        (SourceCode):
+        (UnlinkedFunctionExecutable):
+        (VM):
+        * interpreter/CachedCall.h:
+        (JSC::CachedCall::CachedCall):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::makeFunctionCallNode):
+        * parser/Lexer.cpp:
+        (JSC::Lexer<T>::Lexer):
+        (JSC::isSafeBuiltinIdentifier):
+        (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/ArrayPrototype.cpp:
+        * runtime/CodeCache.cpp:
+        (JSC::CodeCache::getFunctionExecutableFromGlobalCode):
+        * runtime/CommonIdentifiers.cpp:
+        (JSC::CommonIdentifiers::CommonIdentifiers):
+        (JSC::CommonIdentifiers::~CommonIdentifiers):
+        (JSC::CommonIdentifiers::getPrivateName):
+        (JSC::CommonIdentifiers::getPublicName):
+        * runtime/CommonIdentifiers.h:
+        (JSC::CommonIdentifiers::builtinNames):
+        * 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/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/JSFunctionInlines.h:
+        (JSC::JSFunction::nativeFunction):
+        (JSC::JSFunction::nativeConstructor):
+        (JSC::isHostFunction):
+        * 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/JSSymbolTableObject.cpp:
+        (JSC::JSSymbolTableObject::getOwnNonIndexPropertyNames):
+        * 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/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+        (JSC::VM::builtinExecutables):
+
 2014-02-11  Brent Fulgham  <bfulgham@apple.com>
 
         Remove some unintended copies in ranged for loops
index 6027466..4354056 100644 (file)
@@ -28,8 +28,9 @@ VPATH = \
     $(JavaScriptCore) \
     $(JavaScriptCore)/parser \
     $(JavaScriptCore)/runtime \
-    $(JavaScriptCore)/interpreter \
-    $(JavaScriptCore)/jit \
+       $(JavaScriptCore)/interpreter \
+       $(JavaScriptCore)/jit \
+       $(JavaScriptCore)/builtins \
 #
 
 .PHONY : all
@@ -57,8 +58,18 @@ all : \
     RegExpObject.lut.h \
     StringConstructor.lut.h \
     udis86_itab.h \
+    JSCBuiltins \
 #
 
+# builtin functions
+.PHONY: JSCBuiltins
+
+JSCBuiltins: $(JavaScriptCore)/generate-js-builtins JSCBuiltins.h JSCBuiltins.cpp
+JSCBuiltins.h: $(JavaScriptCore)/generate-js-builtins $(JavaScriptCore)/builtins/*.js
+       python $^ $@
+                                                                                                                                                                
+JSCBuiltins.cpp: JSCBuiltins.h
+
 # lookup tables for classes
 
 %.lut.h: create_hash_table %.cpp
index cc3bc19..ad73b78 100644 (file)
@@ -51,6 +51,7 @@ javascriptcore_cppflags += \
        -I$(srcdir)/Source/JavaScriptCore/ForwardingHeaders \
        -I$(srcdir)/Source/JavaScriptCore/assembler \
        -I$(srcdir)/Source/JavaScriptCore/bindings \
+       -I$(srcdir)/Source/JavaScriptCore/builtins \
        -I$(srcdir)/Source/JavaScriptCore/bytecode \
        -I$(srcdir)/Source/JavaScriptCore/bytecompiler \
        -I$(srcdir)/Source/JavaScriptCore/debugger \
@@ -110,12 +111,16 @@ DerivedSources/JavaScriptCore/LLIntDesiredOffsets.h: $(javascriptcore_sources) $
        $(AM_V_GEN)$(RUBY) $(srcdir)/Source/JavaScriptCore/offlineasm/generate_offset_extractor.rb $(srcdir)/Source/JavaScriptCore/llint/LowLevelInterpreter.asm $@
        $(AM_V_at)touch $@
 
-$(Programs_LLIntOffsetsExtractor_OBJECTS): DerivedSources/JavaScriptCore/LLIntDesiredOffsets.h
+$(Programs_LLIntOffsetsExtractor_OBJECTS): DerivedSources/JavaScriptCore/LLIntDesiredOffsets.h 
 
 DerivedSources/JavaScriptCore/LLIntAssembly.h: Programs/LLIntOffsetsExtractor$(EXEEXT)
        $(AM_V_GEN)$(RUBY) $(srcdir)/Source/JavaScriptCore/offlineasm/asm.rb $(srcdir)/Source/JavaScriptCore/llint/LowLevelInterpreter.asm Programs/LLIntOffsetsExtractor$(EXEEXT) $@
        $(AM_V_at)touch $@
 
+DerivedSources/JavaScriptCore/JSCBuiltins.h: DerivedSources/JavaScriptCore/JSCBuiltins.cpp
+DerivedSources/JavaScriptCore/JSCBuiltins.cpp: $(srcdir)/Source/JavaScriptCore/generate-js-builtins $(javascriptcore_builtins_js_nosources)
+       $(AM_V_GEN)$(PYTHON) $^ $@
+
 $(libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_OBJECTS): DerivedSources/JavaScriptCore/LLIntAssembly.h
 
 jsc: $(javascriptcore_built_nosources) Programs/jsc$(EXEEXT)
@@ -217,6 +222,7 @@ EXTRA_DIST += \
        Source/JavaScriptCore/KeywordLookupGenerator.py \
        Source/JavaScriptCore/parser/Keywords.table \
        Source/JavaScriptCore/THANKS \
+       $(javascriptcore_builtins_js_nosources) \
        $(llint_nosources) \
        $(offlineasm_nosources)
 
index b6041c5..fc40641 100644 (file)
@@ -20,6 +20,8 @@ javascriptcore_built_nosources += \
        DerivedSources/JavaScriptCore/ErrorPrototype.lut.h \
        DerivedSources/JavaScriptCore/JSDataViewPrototype.lut.h \
        DerivedSources/JavaScriptCore/JSGlobalObject.lut.h \
+       DerivedSources/JavaScriptCore/JSCBuiltins.cpp \
+       DerivedSources/JavaScriptCore/JSCBuiltins.h \
        DerivedSources/JavaScriptCore/JSONObject.lut.h \
        DerivedSources/JavaScriptCore/JSPromiseConstructor.lut.h \
        DerivedSources/JavaScriptCore/JSPromisePrototype.lut.h \
@@ -35,6 +37,9 @@ javascriptcore_built_nosources += \
        DerivedSources/JavaScriptCore/LLIntDesiredOffsets.h \
        DerivedSources/JavaScriptCore/LLIntAssembly.h
 
+javascriptcore_builtins_js_nosources += \
+       Source/JavaScriptCore/builtins/Array.prototype.js
+
 javascriptcore_sources += \
        Source/JavaScriptCore/API/APICallbackFunction.h \
        Source/JavaScriptCore/API/APICast.h \
@@ -102,6 +107,8 @@ javascriptcore_sources += \
     Source/JavaScriptCore/bindings/ScriptObject.h \
     Source/JavaScriptCore/bindings/ScriptValue.cpp \
     Source/JavaScriptCore/bindings/ScriptValue.h \
+    Source/JavaScriptCore/builtins/BuiltinExecutables.cpp \
+    Source/JavaScriptCore/builtins/BuiltinExecutables.h \
        Source/JavaScriptCore/bytecode/ArrayAllocationProfile.cpp \
        Source/JavaScriptCore/bytecode/ArrayAllocationProfile.h \
        Source/JavaScriptCore/bytecode/ArrayProfile.cpp \
@@ -1271,7 +1278,9 @@ javascriptcore_sources += \
        DerivedSources/JavaScriptCore/InspectorJSFrontendDispatchers.cpp \
        DerivedSources/JavaScriptCore/InspectorJSFrontendDispatchers.h \
        DerivedSources/JavaScriptCore/InspectorJSTypeBuilders.cpp \
-       DerivedSources/JavaScriptCore/InspectorJSTypeBuilders.h
+       DerivedSources/JavaScriptCore/InspectorJSTypeBuilders.h \
+       DerivedSources/JavaScriptCore/JSCBuiltins.cpp \
+       DerivedSources/JavaScriptCore/JSCBuiltins.h
 
 llint_nosources += \
        Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm \
index a2a0b60..99de143 100644 (file)
     <ClCompile Include="..\bindings\ScriptFunctionCall.cpp" />
     <ClCompile Include="..\bindings\ScriptObject.cpp" />
     <ClCompile Include="..\bindings\ScriptValue.cpp" />
+    <ClInclude Include="..\builtins\BuiltinExecutables.cpp" />
     <ClCompile Include="..\bytecode\ArrayAllocationProfile.cpp" />
     <ClCompile Include="..\bytecode\ArrayProfile.cpp" />
     <ClCompile Include="..\bytecode\BytecodeBasicBlock.cpp" />
     <ClCompile Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\InspectorJSBackendDispatchers.cpp" />
     <ClCompile Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\InspectorJSFrontendDispatchers.cpp" />
     <ClCompile Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\InspectorJSTypeBuilders.cpp" />
+    <ClCompile Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\JSCBuiltins.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\ArrayConstructor.lut.h" />
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\RegExpObject.lut.h" />
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\RegExpPrototype.lut.h" />
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\StringConstructor.lut.h" />
+    <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\JSCBuiltins.h" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\API\APICallbackFunction.h" />
     <ClInclude Include="..\bindings\ScriptFunctionCall.h" />
     <ClInclude Include="..\bindings\ScriptObject.h" />
     <ClInclude Include="..\bindings\ScriptValue.h" />
+    <ClInclude Include="..\builtins\BuiltinExecutables.h" />
     <ClInclude Include="..\bytecode\ArrayAllocationProfile.h" />
     <ClInclude Include="..\bytecode\ArrayProfile.h" />
     <ClInclude Include="..\bytecode\ByValInfo.h" />
index b9ea566..d4c7f6e 100644 (file)
@@ -7,6 +7,9 @@
     <Filter Include="bindings">
       <UniqueIdentifier>{0bace123-4582-eebc-9314-7819b376c198}</UniqueIdentifier>
     </Filter>
+    <Filter Include="builtins">
+      <UniqueIdentifier>{3b9d72a5-135b-43b3-a524-c6d2b9d29d35}</UniqueIdentifier>
+    </Filter>
     <Filter Include="bytecode">
       <UniqueIdentifier>{766088a0-1216-4854-aa43-560c5e283668}</UniqueIdentifier>
     </Filter>
     <ClCompile Include="..\assembler\MacroAssembler.cpp">
       <Filter>assembler</Filter>
     </ClCompile>
+    <ClCompile Include="..\builtins\BuiltinExecutables.cpp">
+      <Filter>builtins</Filter>
+    </ClCompile>
     <ClCompile Include="..\bytecode\ArrayAllocationProfile.cpp">
       <Filter>bytecode</Filter>
     </ClCompile>
     <ClCompile Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\InspectorJSTypeBuilders.cpp">
       <Filter>Derived Sources</Filter>
     </ClCompile>
+    <ClCompile Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\JSCBuiltins.cpp">
+      <Filter>Derived Sources</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\API\APICallbackFunction.h">
     <ClInclude Include="..\assembler\X86Assembler.h">
       <Filter>assembler</Filter>
     </ClInclude>
+    <ClCompile Include="..\builtins\BuiltinExecutables.h">
+      <Filter>builtins</Filter>
+    </ClCompile>
     <ClInclude Include="..\bytecode\ArrayAllocationProfile.h">
       <Filter>bytecode</Filter>
     </ClInclude>
     <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\ArrayPrototype.lut.h">
       <Filter>Derived Sources</Filter>
     </ClInclude>
+    <ClInclude Include="$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\$(ProjectName)\DerivedSources\JSCBuiltins.h">
+      <Filter>Derived Sources</Filter>
+    </ClInclude>
     <ClInclude Include="..\runtime\VM.h">
       <Filter>runtime</Filter>
     </ClInclude>
index 3622ffc..c588870 100644 (file)
@@ -5,7 +5,7 @@
   <PropertyGroup />
   <ItemDefinitionGroup>
     <ClCompile>
-      <AdditionalIncludeDirectories>..\;..\tools\;..\runtime\;..\llint\;..\jit\;..\disassembler\;..\heap\;..\debugger\;..\assembler\;..\profiler\;..\yarr\;..\interpreter\;..\bytecode\;..\dfg\;..\bytecompiler\;..\parser\;..\API\;..\ftl\;..\bindings\;..\inspector\;$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\JavaScriptCore\DerivedSources\;$(ConfigurationBuildDir)\include\;$(ConfigurationBuildDir)\include\JavaScriptCore\;$(ConfigurationBuildDir)\include\private\;$(WebKit_Libraries)\include;$(WebKit_Libraries)\include\private;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>..\;..\tools\;..\runtime\;..\llint\;..\jit\;..\disassembler\;..\heap\;..\debugger\;..\assembler\;..\profiler\;..\yarr\;..\interpreter\;..\bytecode\;..\builtins\;..\dfg\;..\bytecompiler\;..\parser\;..\API\;..\ftl\;..\bindings\;..\inspector\;$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\JavaScriptCore\DerivedSources\;$(ConfigurationBuildDir)\include\;$(ConfigurationBuildDir)\include\JavaScriptCore\;$(ConfigurationBuildDir)\include\private\;$(WebKit_Libraries)\include;$(WebKit_Libraries)\include\private;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <ForcedIncludeFiles>ICUVersion.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
     </ClCompile>
     <Link>
index 943343a..e0c1f29 100755 (executable)
@@ -42,6 +42,7 @@ for %%d in (
     assembler\r
     bindings\r
     bytecode\r
+    builtins\r
     dfg\r
     disassembler\r
     heap\r
@@ -72,6 +73,9 @@ xcopy /y "%DerivedSourcesDirectory%\InspectorJSTypeBuilders.h" "%PrivateHeadersD
 xcopy /y "%DerivedSourcesDirectory%\InspectorJSBackendDispatchers.h" "%PrivateHeadersDirectory%" >NUL\r
 xcopy /y "%DerivedSourcesDirectory%\InspectorJSFrontendDispatchers.h" "%PrivateHeadersDirectory%" >NUL\r
 \r
+echo Copying builtins header as if it were a private header...\r
+xcopy /y "%DerivedSourcesDirectory%\JSCBuiltins.h" "%PrivateHeadersDirectory%" >NUL\r
+\r
 echo Copying resources...\r
 mkdir "%ResourcesDirectory%" 2>NUL\r
 xcopy /y /d JavaScriptCore.resources\* "%ResourcesDirectory%" >NUL\r
index cf68610..7777f8d 100644 (file)
                A74DEF95182D991400522C22 /* JSMapIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A74DEF8F182D991400522C22 /* JSMapIterator.cpp */; };
                A74DEF96182D991400522C22 /* JSMapIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = A74DEF90182D991400522C22 /* JSMapIterator.h */; };
                A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */; };
+               A75EE9B218AAB7E200AAD043 /* BuiltinNames.h in Headers */ = {isa = PBXBuildFile; fileRef = A75EE9B018AAB7E200AAD043 /* BuiltinNames.h */; };
                A76140CD182982CB00750624 /* ArgumentsIteratorConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A76140C7182982CB00750624 /* ArgumentsIteratorConstructor.cpp */; };
                A76140CE182982CB00750624 /* ArgumentsIteratorConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = A76140C8182982CB00750624 /* ArgumentsIteratorConstructor.h */; };
                A76140CF182982CB00750624 /* ArgumentsIteratorPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A76140C9182982CB00750624 /* ArgumentsIteratorPrototype.cpp */; };
                A7CA3AE817DA41AE006538AF /* JSWeakMap.h in Headers */ = {isa = PBXBuildFile; fileRef = A7CA3AE217DA41AE006538AF /* JSWeakMap.h */; };
                A7CA3AEB17DA5168006538AF /* WeakMapData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7CA3AE917DA5168006538AF /* WeakMapData.cpp */; };
                A7CA3AEC17DA5168006538AF /* WeakMapData.h in Headers */ = {isa = PBXBuildFile; fileRef = A7CA3AEA17DA5168006538AF /* WeakMapData.h */; };
+               A7D801A41880D66E0026C39B /* BuiltinExecutables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7D801A11880D66E0026C39B /* BuiltinExecutables.cpp */; };
+               A7D801A51880D66E0026C39B /* BuiltinExecutables.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D801A21880D66E0026C39B /* BuiltinExecutables.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               A7D801A81880D6A80026C39B /* JSCBuiltins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7D801A61880D6A80026C39B /* JSCBuiltins.cpp */; };
+               A7D801A91880D6A80026C39B /* JSCBuiltins.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D801A71880D6A80026C39B /* JSCBuiltins.h */; };
                A7D89CF217A0B8CC00773AD8 /* DFGBasicBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7D89CE317A0B8CC00773AD8 /* DFGBasicBlock.cpp */; };
                A7D89CF317A0B8CC00773AD8 /* DFGBlockInsertionSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7D89CE417A0B8CC00773AD8 /* DFGBlockInsertionSet.cpp */; };
                A7D89CF417A0B8CC00773AD8 /* DFGBlockInsertionSet.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D89CE517A0B8CC00773AD8 /* DFGBlockInsertionSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
                14D857740A4696C80032146C /* testapi.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = testapi.js; path = API/tests/testapi.js; sourceTree = "<group>"; };
                14DA818E0D99FD2000B0A4FB /* JSActivation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSActivation.h; sourceTree = "<group>"; };
                14DA818F0D99FD2000B0A4FB /* JSActivation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSActivation.cpp; sourceTree = "<group>"; };
-               14DE0D680D02431400AACCA2 /* JSGlobalObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalObject.cpp; sourceTree = "<group>"; };
+               14DE0D680D02431400AACCA2 /* JSGlobalObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = JSGlobalObject.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
                14DF04D916B3996D0016A513 /* StaticPropertyAnalysis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StaticPropertyAnalysis.h; sourceTree = "<group>"; };
                14E84F9914EE1ACC00D6D5D4 /* WeakBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WeakBlock.cpp; sourceTree = "<group>"; };
                14E84F9A14EE1ACC00D6D5D4 /* WeakBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakBlock.h; sourceTree = "<group>"; };
                65FB5115184EE8F800C12B70 /* ProtoCallFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProtoCallFrame.h; sourceTree = "<group>"; };
                65FB5116184EE9BC00C12B70 /* ProtoCallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProtoCallFrame.cpp; sourceTree = "<group>"; };
                704FD35305697E6D003DBED9 /* BooleanObject.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = BooleanObject.h; sourceTree = "<group>"; tabWidth = 8; };
-               7C008CD0186F8A9300955C24 /* JSPromiseFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPromiseFunctions.cpp; sourceTree = "<group>"; };
+               7C008CD0186F8A9300955C24 /* JSPromiseFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = JSPromiseFunctions.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
                7C008CD1186F8A9300955C24 /* JSPromiseFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPromiseFunctions.h; sourceTree = "<group>"; };
                7C008CD8187124BB00955C24 /* JSPromiseDeferred.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPromiseDeferred.cpp; sourceTree = "<group>"; };
                7C008CD9187124BB00955C24 /* JSPromiseDeferred.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPromiseDeferred.h; sourceTree = "<group>"; };
                7C008CE5187631B600955C24 /* Microtask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Microtask.h; sourceTree = "<group>"; };
                7C184E1817BEDBD3007CB63A /* JSPromise.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPromise.cpp; sourceTree = "<group>"; };
                7C184E1917BEDBD3007CB63A /* JSPromise.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPromise.h; sourceTree = "<group>"; };
-               7C184E1C17BEE22E007CB63A /* JSPromisePrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPromisePrototype.cpp; sourceTree = "<group>"; };
+               7C184E1C17BEE22E007CB63A /* JSPromisePrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = JSPromisePrototype.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
                7C184E1D17BEE22E007CB63A /* JSPromisePrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPromisePrototype.h; sourceTree = "<group>"; };
-               7C184E2017BEE240007CB63A /* JSPromiseConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPromiseConstructor.cpp; sourceTree = "<group>"; };
+               7C184E2017BEE240007CB63A /* JSPromiseConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = JSPromiseConstructor.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
                7C184E2117BEE240007CB63A /* JSPromiseConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPromiseConstructor.h; sourceTree = "<group>"; };
                7C184E2417BFFA36007CB63A /* JSPromiseConstructor.lut.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSPromiseConstructor.lut.h; sourceTree = "<group>"; };
                7C184E2517BFFA36007CB63A /* JSPromisePrototype.lut.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSPromisePrototype.lut.h; sourceTree = "<group>"; };
                A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITOpcodes32_64.cpp; sourceTree = "<group>"; };
                A718F61A11754A21002465A7 /* RegExpJitTables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpJitTables.h; sourceTree = "<group>"; };
                A718F8211178EB4B002465A7 /* create_regex_tables */ = {isa = PBXFileReference; explicitFileType = text.script.python; fileEncoding = 4; path = create_regex_tables; sourceTree = "<group>"; };
+               A71DA80D1880D71F00D1F299 /* generate-js-builtins */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = "generate-js-builtins"; sourceTree = "<group>"; };
                A72028B41797601E0098028C /* JSCTestRunnerUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCTestRunnerUtils.cpp; sourceTree = "<group>"; };
                A72028B51797601E0098028C /* JSCTestRunnerUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCTestRunnerUtils.h; sourceTree = "<group>"; };
                A72028B91797603D0098028C /* JSFunctionInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFunctionInlines.h; sourceTree = "<group>"; };
                A74DEF8F182D991400522C22 /* JSMapIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMapIterator.cpp; sourceTree = "<group>"; };
                A74DEF90182D991400522C22 /* JSMapIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMapIterator.h; sourceTree = "<group>"; };
                A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITArithmetic32_64.cpp; sourceTree = "<group>"; };
+               A75EE9B018AAB7E200AAD043 /* BuiltinNames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuiltinNames.h; sourceTree = "<group>"; };
                A76140C7182982CB00750624 /* ArgumentsIteratorConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArgumentsIteratorConstructor.cpp; sourceTree = "<group>"; };
                A76140C8182982CB00750624 /* ArgumentsIteratorConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArgumentsIteratorConstructor.h; sourceTree = "<group>"; };
-               A76140C9182982CB00750624 /* ArgumentsIteratorPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArgumentsIteratorPrototype.cpp; sourceTree = "<group>"; };
+               A76140C9182982CB00750624 /* ArgumentsIteratorPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = ArgumentsIteratorPrototype.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
                A76140CA182982CB00750624 /* ArgumentsIteratorPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArgumentsIteratorPrototype.h; sourceTree = "<group>"; };
                A76140CB182982CB00750624 /* JSArgumentsIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSArgumentsIterator.cpp; sourceTree = "<group>"; };
                A76140CC182982CB00750624 /* JSArgumentsIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSArgumentsIterator.h; sourceTree = "<group>"; };
                A7B4ACAE1484C9CE00B38A36 /* JSExportMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSExportMacros.h; sourceTree = "<group>"; };
                A7BDAEC017F4EA1400F6140C /* ArrayIteratorConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayIteratorConstructor.cpp; sourceTree = "<group>"; };
                A7BDAEC117F4EA1400F6140C /* ArrayIteratorConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayIteratorConstructor.h; sourceTree = "<group>"; };
-               A7BDAEC217F4EA1400F6140C /* ArrayIteratorPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayIteratorPrototype.cpp; sourceTree = "<group>"; };
+               A7BDAEC217F4EA1400F6140C /* ArrayIteratorPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = ArrayIteratorPrototype.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
                A7BDAEC317F4EA1400F6140C /* ArrayIteratorPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayIteratorPrototype.h; sourceTree = "<group>"; };
-               A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSArrayIterator.cpp; sourceTree = "<group>"; };
+               A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = JSArrayIterator.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
                A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSArrayIterator.h; sourceTree = "<group>"; };
                A7BFF3BF179868940002F462 /* DFGFiltrationResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGFiltrationResult.h; path = dfg/DFGFiltrationResult.h; sourceTree = "<group>"; };
                A7C0C4AA167C08CD0017011D /* JSScriptRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSScriptRef.cpp; sourceTree = "<group>"; };
                A7CA3AE217DA41AE006538AF /* JSWeakMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWeakMap.h; sourceTree = "<group>"; };
                A7CA3AE917DA5168006538AF /* WeakMapData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WeakMapData.cpp; sourceTree = "<group>"; };
                A7CA3AEA17DA5168006538AF /* WeakMapData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakMapData.h; sourceTree = "<group>"; };
+               A7D801A01880D66E0026C39B /* Array.prototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = Array.prototype.js; sourceTree = "<group>"; };
+               A7D801A11880D66E0026C39B /* BuiltinExecutables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BuiltinExecutables.cpp; sourceTree = "<group>"; };
+               A7D801A21880D66E0026C39B /* BuiltinExecutables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BuiltinExecutables.h; sourceTree = "<group>"; };
+               A7D801A61880D6A80026C39B /* JSCBuiltins.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCBuiltins.cpp; sourceTree = "<group>"; };
+               A7D801A71880D6A80026C39B /* JSCBuiltins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCBuiltins.h; sourceTree = "<group>"; };
                A7D89CE317A0B8CC00773AD8 /* DFGBasicBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGBasicBlock.cpp; path = dfg/DFGBasicBlock.cpp; sourceTree = "<group>"; };
                A7D89CE417A0B8CC00773AD8 /* DFGBlockInsertionSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGBlockInsertionSet.cpp; path = dfg/DFGBlockInsertionSet.cpp; sourceTree = "<group>"; };
                A7D89CE517A0B8CC00773AD8 /* DFGBlockInsertionSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBlockInsertionSet.h; path = dfg/DFGBlockInsertionSet.h; sourceTree = "<group>"; };
                F5BB2BC5030F772101FCFE1D /* Completion.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Completion.h; sourceTree = "<group>"; tabWidth = 8; };
                F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptCorePrefix.h; sourceTree = "<group>"; tabWidth = 8; };
                F68EBB8C0255D4C601FF60F7 /* config.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; tabWidth = 8; };
-               F692A84D0255597D01FF60F7 /* ArrayPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayPrototype.cpp; sourceTree = "<group>"; tabWidth = 8; };
+               F692A84D0255597D01FF60F7 /* ArrayPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = ArrayPrototype.cpp; sourceTree = "<group>"; tabWidth = 8; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
                F692A84E0255597D01FF60F7 /* ArrayPrototype.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ArrayPrototype.h; sourceTree = "<group>"; tabWidth = 8; };
                F692A8500255597D01FF60F7 /* BooleanObject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BooleanObject.cpp; sourceTree = "<group>"; tabWidth = 8; };
                F692A8540255597D01FF60F7 /* create_hash_table */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = text.script.perl; path = create_hash_table; sourceTree = "<group>"; tabWidth = 8; };
                                8604F4F2143A6C4400B295F5 /* ChangeLog */,
                                F692A8540255597D01FF60F7 /* create_hash_table */,
                                A718F8211178EB4B002465A7 /* create_regex_tables */,
+                               A71DA80D1880D71F00D1F299 /* generate-js-builtins */,
                                45E12D8806A49B0F00E9DF84 /* jsc.cpp */,
                                F68EBB8C0255D4C601FF60F7 /* config.h */,
                                F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */,
                                1432EBD70A34CAD400717B9F /* API */,
                                9688CB120ED12B4E001D649F /* assembler */,
                                A54CF2EA184EA73900237F19 /* bindings */,
+                               A7D8019F1880D66E0026C39B /* builtins */,
                                969A078F0ED1D3AE00F1F681 /* bytecode */,
                                7E39D81D0EC38EFA003AF11A /* bytecompiler */,
                                1C90513E0BA9E8830081E9D0 /* Configurations */,
                650FDF8D09D0FCA700769E54 /* Derived Sources */ = {
                        isa = PBXGroup;
                        children = (
+                               A7D801A61880D6A80026C39B /* JSCBuiltins.cpp */,
+                               A7D801A71880D6A80026C39B /* JSCBuiltins.h */,
                                BC18C5230E16FC8A00B34460 /* ArrayPrototype.lut.h */,
                                BCD203E70E1718F4002C7E82 /* DatePrototype.lut.h */,
                                A513E5C6185F9436007E95AD /* InjectedScriptSource.h */,
                        path = remote;
                        sourceTree = "<group>";
                };
+               A7D8019F1880D66E0026C39B /* builtins */ = {
+                       isa = PBXGroup;
+                       children = (
+                               A7D801A01880D66E0026C39B /* Array.prototype.js */,
+                               A7D801A11880D66E0026C39B /* BuiltinExecutables.cpp */,
+                               A7D801A21880D66E0026C39B /* BuiltinExecutables.h */,
+                               A75EE9B018AAB7E200AAD043 /* BuiltinNames.h */,
+                       );
+                       path = builtins;
+                       sourceTree = "<group>";
+               };
 /* End PBXGroup section */
 
 /* Begin PBXHeadersBuildPhase section */
                                0FD81AD3154FB4F000983E72 /* DFGDominators.h in Headers */,
                                0F1E3A471534CBB9000F9456 /* DFGDoubleFormatState.h in Headers */,
                                0FD3C82814115D4F00FD81CB /* DFGDriver.h in Headers */,
+                               A75EE9B218AAB7E200AAD043 /* BuiltinNames.h in Headers */,
                                0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */,
                                A7D9A29617A0BC7400EE2618 /* DFGEdgeDominates.h in Headers */,
                                A7986D5717A0BB1E00A95DD0 /* DFGEdgeUsesStructure.h in Headers */,
                                0FEA0A1D1708B00700BB722C /* FTLAbstractHeap.h in Headers */,
                                0FEA0A1F1708B00700BB722C /* FTLAbstractHeapRepository.h in Headers */,
                                A59455931824744700CC3843 /* JSGlobalObjectDebuggable.h in Headers */,
+                               A7D801A91880D6A80026C39B /* JSCBuiltins.h in Headers */,
                                0FEA0A0A170513DB00BB722C /* FTLCapabilities.h in Headers */,
                                0F48532A187DFDEC0083B687 /* FTLRecoveryOpcode.h in Headers */,
                                0FEA0A231709606900BB722C /* FTLCommonValues.h in Headers */,
                                BC18C40F0E16F5CD00B34460 /* Identifier.h in Headers */,
                                C25F8BCE157544A900245B71 /* IncrementalSweeper.h in Headers */,
                                0FB7F39915ED8E4600F167B2 /* IndexingHeader.h in Headers */,
+                               A7D801A51880D66E0026C39B /* BuiltinExecutables.h in Headers */,
                                0FB7F39A15ED8E4600F167B2 /* IndexingHeaderInlines.h in Headers */,
                                0FB7F39B15ED8E4600F167B2 /* IndexingType.h in Headers */,
                                0FCEFAB01805CA6D00472CE4 /* InitializeLLVM.h in Headers */,
                                A7D89CF217A0B8CC00773AD8 /* DFGBasicBlock.cpp in Sources */,
                                A70B083217A0B79B00DAF14B /* DFGBinarySwitch.cpp in Sources */,
                                A7D89CF317A0B8CC00773AD8 /* DFGBlockInsertionSet.cpp in Sources */,
+                               A7D801A41880D66E0026C39B /* BuiltinExecutables.cpp in Sources */,
                                86EC9DC41328DF82002B2AD7 /* DFGByteCodeParser.cpp in Sources */,
                                0FD82E2114172CE300179C94 /* DFGCapabilities.cpp in Sources */,
                                0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */,
                                0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */,
                                0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */,
                                0F8F2B99172F04FF007DBDA5 /* DFGDesiredIdentifiers.cpp in Sources */,
+                               A7D801A81880D6A80026C39B /* JSCBuiltins.cpp in Sources */,
                                A73E1330179624CD00E4DEA8 /* DFGDesiredStructureChains.cpp in Sources */,
                                C2C0F7CD17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp in Sources */,
                                0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */,
diff --git a/Source/JavaScriptCore/builtins/Array.prototype.js b/Source/JavaScriptCore/builtins/Array.prototype.js
new file mode 100644 (file)
index 0000000..3eb42f5
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 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.
+ */
+
+function every(callback /*, thisArg */) {
+    "use strict";
+    if (this === null)
+        throw new @TypeError("Array.prototype.every requires that |this| not be null");
+    
+    if (this === undefined)
+        throw new @TypeError("Array.prototype.every requires that |this| not be undefined");
+    
+    var array = @Object(this);
+    var length = array.length >>> 0;
+    
+    if (typeof callback !== "function")
+        throw new @TypeError("Array.prototype.every callback must be a function");
+
+    var thisArg = arguments.length > 1 ? arguments[1] : undefined;
+    
+    for (var i = 0; i < length; i++) {
+        if (!(i in array))
+            continue;
+        if (!callback.@call(thisArg, array[i], i, array))
+            return false;
+    }
+    
+    return true;
+}
+
diff --git a/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp b/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp
new file mode 100644 (file)
index 0000000..a900813
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 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.
+ */
+
+
+#include "config.h"
+#include "BuiltinExecutables.h"
+
+#include "BuiltinNames.h"
+#include "Executable.h"
+#include "JSCInlines.h"
+#include "Parser.h"
+
+namespace JSC {
+
+BuiltinExecutables::BuiltinExecutables(VM& vm)
+    : m_vm(vm)
+#define INITIALIZE_BUILTIN_SOURCE_MEMBERS(name, functionName, length) , m_##name##Source(makeSource(StringImpl::createFromLiteral(s_##name, length), StringImpl::createFromLiteral("<builtin>")))
+    JSC_FOREACH_BUILTIN(INITIALIZE_BUILTIN_SOURCE_MEMBERS)
+#undef EXPOSE_BUILTIN_STRINGS
+{
+}
+
+UnlinkedFunctionExecutable* BuiltinExecutables::createBuiltinExecutable(const SourceCode& source, const Identifier& name)
+{
+    JSTextPosition positionBeforeLastNewline;
+    ParserError error;
+    RefPtr<ProgramNode> program = parse<ProgramNode>(&m_vm, source, 0, Identifier(), JSParseBuiltin, JSParseProgramCode, error, &positionBeforeLastNewline);
+
+    if (!program) {
+        dataLog("Fatal error compiling builtin function '", name.string(), "': ", error.m_message);
+        CRASH();
+    }
+
+    StatementNode* exprStatement = program->singleStatement();
+    RELEASE_ASSERT(exprStatement);
+    RELEASE_ASSERT(exprStatement->isExprStatement());
+    ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
+    RELEASE_ASSERT(funcExpr);
+    RELEASE_ASSERT(funcExpr->isFuncExprNode());
+    FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
+    RELEASE_ASSERT(!program->hasCapturedVariables());
+    
+    body->setEndPosition(positionBeforeLastNewline);
+    RELEASE_ASSERT(body);
+    RELEASE_ASSERT(body->ident().isNull());
+    
+    // This function assumes an input string that would result in a single anonymous function expression.
+    body->setEndPosition(positionBeforeLastNewline);
+    RELEASE_ASSERT(body);
+    for (const auto& closedVariable : program->closedVariables()) {
+        if (closedVariable == m_vm.propertyNames->arguments.impl())
+        continue;
+        
+        if (closedVariable == m_vm.propertyNames->undefinedKeyword.impl())
+            continue;
+        RELEASE_ASSERT(closedVariable->isEmptyUnique());
+    }
+    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&m_vm, source, body, true, UnlinkedBuiltinFunction);
+    functionExecutable->m_nameValue.set(m_vm, functionExecutable, jsString(&m_vm, name.string()));
+    return functionExecutable;
+}
+
+#define DEFINE_BUILTIN_EXECUTABLES(name, functionName, length) \
+UnlinkedFunctionExecutable* BuiltinExecutables::name##Executable() \
+{\
+    if (!m_##name##Executable)\
+        m_##name##Executable = createBuiltinExecutable(m_##name##Source, m_vm.propertyNames->builtinNames().functionName());\
+    return m_##name##Executable.get();\
+}
+JSC_FOREACH_BUILTIN(DEFINE_BUILTIN_EXECUTABLES)
+#undef EXPOSE_BUILTIN_SOURCES
+
+}
diff --git a/Source/JavaScriptCore/builtins/BuiltinExecutables.h b/Source/JavaScriptCore/builtins/BuiltinExecutables.h
new file mode 100644 (file)
index 0000000..d9a19e2
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 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 BuiltinExecutables_h
+#define BuiltinExecutables_h
+
+#include "JSCBuiltins.h"
+#include "SourceCode.h"
+#include "Weak.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace JSC {
+
+class UnlinkedFunctionExecutable;
+class Identifier;
+class VM;
+
+class BuiltinExecutables {
+public:
+    static PassOwnPtr<BuiltinExecutables> create(VM& vm)
+    {
+        return adoptPtr(new BuiltinExecutables(vm));
+    }
+    
+#define EXPOSE_BUILTIN_EXECUTABLES(name, functionName, length) \
+UnlinkedFunctionExecutable* name##Executable(); \
+const SourceCode& name##Source() { return m_##name##Source; }
+    
+    JSC_FOREACH_BUILTIN(EXPOSE_BUILTIN_EXECUTABLES)
+#undef EXPOSE_BUILTIN_SOURCES
+    
+private:
+    BuiltinExecutables(VM&);
+    VM& m_vm;
+    UnlinkedFunctionExecutable* createBuiltinExecutable(const SourceCode&, const Identifier&);
+#define DECLARE_BUILTIN_SOURCE_MEMBERS(name, functionName, length)\
+    SourceCode m_##name##Source; \
+    Weak<UnlinkedFunctionExecutable> m_##name##Executable;
+    JSC_FOREACH_BUILTIN(DECLARE_BUILTIN_SOURCE_MEMBERS)
+#undef DECLARE_BUILTIN_SOURCE_MEMBERS
+};
+
+}
+
+#endif
diff --git a/Source/JavaScriptCore/builtins/BuiltinNames.h b/Source/JavaScriptCore/builtins/BuiltinNames.h
new file mode 100644 (file)
index 0000000..f81ab6e
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 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 BuiltinNames_h
+#define BuiltinNames_h
+
+#include "CommonIdentifiers.h"
+#include "JSCBuiltins.h"
+
+namespace JSC {
+    
+#define INITIALISE_BUILTIN_NAMES(name) , m_##name(vm, #name), m_##name##PrivateName(Identifier::from(PrivateName()))
+#define DECLARE_BUILTIN_NAMES(name) const Identifier m_##name; const Identifier m_##name##PrivateName;;
+#define DECLARE_BUILTIN_IDENTIFIER_ACCESSOR(name) \
+    const Identifier& name() const { return m_##name; } \
+    const Identifier& name##PrivateName() const { return m_##name##PrivateName; }
+
+#define INITIALISE_PRIVATE_TO_PUBLIC_ENTRY(name) m_privateToPublicMap.add(m_##name##PrivateName.impl(), &m_##name);
+#define INITIALISE_PUBLIC_TO_PRIVATE_ENTRY(name) m_publicToPrivateMap.add(m_##name.impl(), &m_##name##PrivateName);
+    
+class BuiltinNames {
+    WTF_MAKE_NONCOPYABLE(BuiltinNames); WTF_MAKE_FAST_ALLOCATED;
+    
+public:
+    BuiltinNames(VM* vm, CommonIdentifiers* commonIdentifiers)
+        : m_emptyIdentifier(commonIdentifiers->emptyIdentifier)
+        JSC_FOREACH_BUILTIN_FUNCTION_NAME(INITIALISE_BUILTIN_NAMES)
+        JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALISE_BUILTIN_NAMES)
+    {
+        JSC_FOREACH_BUILTIN_FUNCTION_NAME(INITIALISE_PRIVATE_TO_PUBLIC_ENTRY)
+        JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALISE_PRIVATE_TO_PUBLIC_ENTRY)
+        JSC_FOREACH_BUILTIN_FUNCTION_NAME(INITIALISE_PUBLIC_TO_PRIVATE_ENTRY)
+        JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALISE_PUBLIC_TO_PRIVATE_ENTRY)
+    }
+
+    const Identifier* getPrivateName(const Identifier&) const;
+    const Identifier& getPublicName(const Identifier&) const;
+    
+    JSC_FOREACH_BUILTIN_FUNCTION_NAME(DECLARE_BUILTIN_IDENTIFIER_ACCESSOR)
+    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(DECLARE_BUILTIN_IDENTIFIER_ACCESSOR)
+
+private:
+    Identifier m_emptyIdentifier;
+    JSC_FOREACH_BUILTIN_FUNCTION_NAME(DECLARE_BUILTIN_NAMES)
+    JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(DECLARE_BUILTIN_NAMES)
+    typedef HashMap<RefPtr<StringImpl>, const Identifier*, IdentifierRepHash> BuiltinNamesMap;
+    BuiltinNamesMap m_publicToPrivateMap;
+    BuiltinNamesMap m_privateToPublicMap;
+};
+
+#undef DECLARE_BUILTIN_NAMES
+#undef INITIALISE_BUILTIN_NAMES
+#undef DECLARE_BUILTIN_IDENTIFIER_ACCESSOR
+
+
+inline const Identifier* BuiltinNames::getPrivateName(const Identifier& ident) const
+{
+    auto iter = m_publicToPrivateMap.find(ident.impl());
+    if (iter != m_publicToPrivateMap.end())
+        return iter->value;
+    return 0;
+}
+
+inline const Identifier& BuiltinNames::getPublicName(const Identifier& ident) const
+{
+    auto iter = m_privateToPublicMap.find(ident.impl());
+    if (iter != m_privateToPublicMap.end())
+        return *iter->value;
+    return m_emptyIdentifier;
+}
+
+    
+}
+
+#endif
index b2d5234..c6bbee1 100644 (file)
@@ -1594,7 +1594,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
 
     setConstantRegisters(unlinkedCodeBlock->constantRegisters());
     if (unlinkedCodeBlock->usesGlobalObject())
-        m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().offset()].set(*m_vm, ownerExecutable, m_globalObject.get());
+        m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(*m_vm, ownerExecutable, m_globalObject.get());
     m_functionDecls.resizeToFit(unlinkedCodeBlock->numberOfFunctionDecls());
     for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) {
         UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
index d883727..cdad4a2 100644 (file)
@@ -49,9 +49,9 @@ const ClassInfo UnlinkedProgramCodeBlock::s_info = { "UnlinkedProgramCodeBlock",
 const ClassInfo UnlinkedEvalCodeBlock::s_info = { "UnlinkedEvalCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedEvalCodeBlock) };
 const ClassInfo UnlinkedFunctionCodeBlock::s_info = { "UnlinkedFunctionCodeBlock", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(UnlinkedFunctionCodeBlock) };
 
-static UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(VM& vm, UnlinkedFunctionExecutable* executable, const SourceCode& source, CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, ParserError& error)
+static UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(VM& vm, UnlinkedFunctionExecutable* executable, const SourceCode& source, CodeSpecializationKind kind, DebuggerMode debuggerMode, ProfilerMode profilerMode, UnlinkedFunctionKind functionKind, ParserError& error)
 {
-    RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(&vm, source, executable->parameters(), executable->name(), executable->isInStrictContext() ? JSParseStrict : JSParseNormal, JSParseFunctionCode, error);
+    RefPtr<FunctionBodyNode> body = parse<FunctionBodyNode>(&vm, source, executable->parameters(), executable->name(), executable->toStrictness(), JSParseFunctionCode, error);
 
     if (!body) {
         ASSERT(error.m_type != ParserError::ErrorNone);
@@ -63,7 +63,7 @@ static UnlinkedFunctionCodeBlock* generateFunctionCodeBlock(VM& vm, UnlinkedFunc
     body->finishParsing(executable->parameters(), executable->name(), executable->functionMode());
     executable->recordParse(body->features(), body->hasCapturedVariables());
     
-    UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, ExecutableInfo(body->needsActivation(), body->usesEval(), body->isStrictMode(), kind == CodeForConstruct));
+    UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, ExecutableInfo(body->needsActivation(), body->usesEval(), body->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction));
     OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(vm, body.get(), result, debuggerMode, profilerMode)));
     error = generator->generate();
     body->destroyData();
@@ -82,13 +82,14 @@ unsigned UnlinkedCodeBlock::addOrFindConstant(JSValue v)
     return addConstant(v);
 }
 
-UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, FunctionBodyNode* node, bool isFromGlobalCode)
+UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& source, FunctionBodyNode* node, bool isFromGlobalCode, UnlinkedFunctionKind kind)
     : Base(*vm, structure)
     , m_numCapturedVariables(node->capturedVariableCount())
     , m_forceUsesArguments(node->usesArguments())
     , m_isInStrictContext(node->isStrictMode())
     , m_hasCapturedVariables(node->hasCapturedVariables())
     , m_isFromGlobalCode(isFromGlobalCode)
+    , m_isBuiltinFunction(kind == UnlinkedBuiltinFunction)
     , m_name(node->ident())
     , m_inferredName(node->inferredName())
     , m_parameters(node->parameters())
@@ -166,7 +167,7 @@ UnlinkedFunctionCodeBlock* UnlinkedFunctionExecutable::codeBlockFor(VM& vm, cons
         break;
     }
 
-    UnlinkedFunctionCodeBlock* result = generateFunctionCodeBlock(vm, this, source, specializationKind, debuggerMode, profilerMode, error);
+    UnlinkedFunctionCodeBlock* result = generateFunctionCodeBlock(vm, this, source, specializationKind, debuggerMode, profilerMode, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, error);
     
     if (error.m_type != ParserError::ErrorNone)
         return 0;
@@ -210,6 +211,7 @@ UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType code
     , m_isStrictMode(info.m_isStrictMode)
     , m_isConstructor(info.m_isConstructor)
     , m_hasCapturedVariables(false)
+    , m_isBuiltinFunction(info.m_isBuiltinFunction)
     , m_firstLine(0)
     , m_lineCount(0)
     , m_endColumn(UINT_MAX)
index b11ab0e..0308b16 100644 (file)
@@ -66,26 +66,35 @@ typedef unsigned UnlinkedObjectAllocationProfile;
 typedef unsigned UnlinkedLLIntCallLinkInfo;
 
 struct ExecutableInfo {
-    ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor)
+    ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction)
         : m_needsActivation(needsActivation)
         , m_usesEval(usesEval)
         , m_isStrictMode(isStrictMode)
         , m_isConstructor(isConstructor)
+        , m_isBuiltinFunction(isBuiltinFunction)
     {
     }
-    bool m_needsActivation;
-    bool m_usesEval;
-    bool m_isStrictMode;
-    bool m_isConstructor;
+    bool m_needsActivation : 1;
+    bool m_usesEval : 1;
+    bool m_isStrictMode : 1;
+    bool m_isConstructor : 1;
+    bool m_isBuiltinFunction : 1;
+};
+
+enum UnlinkedFunctionKind {
+    UnlinkedNormalFunction,
+    UnlinkedBuiltinFunction,
 };
 
 class UnlinkedFunctionExecutable : public JSCell {
 public:
+    friend class BuiltinExecutables;
     friend class CodeCache;
+    friend class VM;
     typedef JSCell Base;
-    static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionBodyNode* node, bool isFromGlobalCode = false)
+    static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionBodyNode* node, bool isFromGlobalCode, UnlinkedFunctionKind unlinkedFunctionKind)
     {
-        UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap)) UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node, isFromGlobalCode);
+        UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap)) UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node, isFromGlobalCode, unlinkedFunctionKind);
         instance->finishCreation(*vm);
         return instance;
     }
@@ -100,6 +109,14 @@ public:
     size_t parameterCount() const;
     bool isInStrictContext() const { return m_isInStrictContext; }
     FunctionMode functionMode() const { return m_functionMode; }
+    JSParserStrictness toStrictness() const
+    {
+        if (m_isBuiltinFunction)
+            return JSParseBuiltin;
+        if (m_isInStrictContext)
+            return JSParseStrict;
+        return JSParseNormal;
+    }
 
     unsigned firstLineOffset() const { return m_firstLineOffset; }
     unsigned lineCount() const { return m_lineCount; }
@@ -142,8 +159,10 @@ public:
     static const bool hasImmortalStructure = true;
     static void destroy(JSCell*);
 
+    bool isBuiltinFunction() const { return m_isBuiltinFunction; }
+
 private:
-    UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionBodyNode*, bool isFromGlobalCode);
+    UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionBodyNode*, bool isFromGlobalCode, UnlinkedFunctionKind);
     WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
     WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;
 
@@ -152,6 +171,7 @@ private:
     bool m_isInStrictContext : 1;
     bool m_hasCapturedVariables : 1;
     bool m_isFromGlobalCode : 1;
+    bool m_isBuiltinFunction : 1;
 
     Identifier m_name;
     Identifier m_inferredName;
@@ -318,6 +338,8 @@ public:
     void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
     bool isNumericCompareFunction() const { return m_isNumericCompareFunction; }
 
+    bool isBuiltinFunction() const { return m_isBuiltinFunction; }
+    
     void shrinkToFit()
     {
         m_jumpTargets.shrinkToFit();
@@ -500,6 +522,7 @@ private:
     bool m_isStrictMode : 1;
     bool m_isConstructor : 1;
     bool m_hasCapturedVariables : 1;
+    bool m_isBuiltinFunction : 1;
     unsigned m_firstLine;
     unsigned m_lineCount;
     unsigned m_endColumn;
index 091fd00..a0f36c4 100644 (file)
@@ -182,6 +182,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedP
 #endif
     , m_usesExceptions(false)
     , m_expressionTooDeep(false)
+    , m_isBuiltinFunction(false)
 {
     m_codeBlock->setNumParameters(1); // Allocate space for "this"
 
@@ -225,7 +226,13 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionBodyNode* functionBody, Unl
 #endif
     , m_usesExceptions(false)
     , m_expressionTooDeep(false)
+    , m_isBuiltinFunction(codeBlock->isBuiltinFunction())
 {
+    if (m_isBuiltinFunction) {
+        m_shouldEmitProfileHooks = false;
+        m_shouldEmitDebugHooks = false;
+    }
+
     m_symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode());
     Vector<Identifier> boundParameterProperties;
     FunctionParameters& parameters = *functionBody->parameters();
@@ -433,6 +440,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCod
 #endif
     , m_usesExceptions(false)
     , m_expressionTooDeep(false)
+    , m_isBuiltinFunction(false)
 {
     m_symbolTable->setUsesNonStrictEval(codeBlock->usesEval() && !codeBlock->isStrictMode());
     m_codeBlock->setNumParameters(1);
index d61bffc..e1e5459 100644 (file)
@@ -462,7 +462,9 @@ namespace JSC {
         bool shouldEmitDebugHooks() { return m_shouldEmitDebugHooks; }
         
         bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
-
+        
+        bool isBuiltinFunction() const { return m_isBuiltinFunction; }
+        
     private:
         friend class Label;
         
@@ -544,7 +546,7 @@ namespace JSC {
         
         UnlinkedFunctionExecutable* makeFunction(FunctionBodyNode* body)
         {
-            return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), body);
+            return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), body, false, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction);
         }
 
         RegisterID* emitInitLazyRegister(RegisterID*);
@@ -678,6 +680,7 @@ namespace JSC {
 
         bool m_usesExceptions;
         bool m_expressionTooDeep;
+        bool m_isBuiltinFunction;
     };
 
 }
index c2ce2aa..73d2f7b 100644 (file)
@@ -535,9 +535,12 @@ RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
     RefPtr<Label> end = generator.newLabel();
     RefPtr<RegisterID> base = generator.emitNode(m_base);
     generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
-    RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
+    RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().call);
     RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
-    generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
+    bool emitCallCheck = !generator.isBuiltinFunction();
+    if (emitCallCheck)
+        generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
+
     {
         if (m_args->m_listNode && m_args->m_listNode->m_expr) {
             ArgumentListNode* oldList = m_args->m_listNode;
@@ -547,24 +550,24 @@ RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
             CallArguments callArguments(generator, m_args);
             generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
             generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
-            generator.emitJump(end.get());
-
             m_args->m_listNode = oldList;
         } else {
             RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
             CallArguments callArguments(generator, m_args);
             generator.emitLoad(callArguments.thisRegister(), jsUndefined());
             generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
-            generator.emitJump(end.get());
         }
     }
-    generator.emitLabel(realCall.get());
-    {
-        CallArguments callArguments(generator, m_args);
-        generator.emitMove(callArguments.thisRegister(), base.get());
-        generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+    if (emitCallCheck) {
+        generator.emitJump(end.get());
+        generator.emitLabel(realCall.get());
+        {
+            CallArguments callArguments(generator, m_args);
+            generator.emitMove(callArguments.thisRegister(), base.get());
+            generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+        }
+        generator.emitLabel(end.get());
     }
-    generator.emitLabel(end.get());
     return returnValue.get();
 }
 
@@ -585,65 +588,67 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
     RefPtr<Label> end = generator.newLabel();
     RefPtr<RegisterID> base = generator.emitNode(m_base);
     generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
-    RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
+    RefPtr<RegisterID> function;
     RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
-    generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
-    {
-        if (mayBeCall) {
-            if (m_args->m_listNode && m_args->m_listNode->m_expr) {
-                ArgumentListNode* oldList = m_args->m_listNode;
-                if (m_args->m_listNode->m_next) {
-                    ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
-                    ASSERT(!m_args->m_listNode->m_next->m_next);
-                    m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.vm(), 0, 0);
-                    RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
-                    CallArguments callArguments(generator, m_args);
-                    generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
-                    generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
-                } else {
-                    m_args->m_listNode = m_args->m_listNode->m_next;
-                    RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
-                    CallArguments callArguments(generator, m_args);
-                    generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
-                    generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
-                }
-                m_args->m_listNode = oldList;
+    bool emitCallCheck = !generator.isBuiltinFunction();
+    if (emitCallCheck) {
+        function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().apply);
+        generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
+    }
+    if (mayBeCall) {
+        if (m_args->m_listNode && m_args->m_listNode->m_expr) {
+            ArgumentListNode* oldList = m_args->m_listNode;
+            if (m_args->m_listNode->m_next) {
+                ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
+                ASSERT(!m_args->m_listNode->m_next->m_next);
+                m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.vm(), 0, 0);
+                RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
+                CallArguments callArguments(generator, m_args);
+                generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
+                generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
             } else {
+                m_args->m_listNode = m_args->m_listNode->m_next;
                 RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
                 CallArguments callArguments(generator, m_args);
-                generator.emitLoad(callArguments.thisRegister(), jsUndefined());
+                generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
                 generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
             }
+            m_args->m_listNode = oldList;
         } else {
-            ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
-            RefPtr<RegisterID> profileHookRegister;
-            if (generator.shouldEmitProfileHooks())
-                profileHookRegister = generator.newTemporary();
             RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
-            RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
-            RefPtr<RegisterID> argsRegister;
-            ArgumentListNode* args = m_args->m_listNode->m_next;
-            if (args->m_expr->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(args->m_expr)->identifier()))
-                argsRegister = generator.uncheckedRegisterForArguments();
-            else
-                argsRegister = generator.emitNode(args->m_expr);
-
-            // Function.prototype.apply ignores extra arguments, but we still
-            // need to evaluate them for side effects.
-            while ((args = args->m_next))
-                generator.emitNode(args->m_expr);
-
-            generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), profileHookRegister.get(), divot(), divotStart(), divotEnd());
+            CallArguments callArguments(generator, m_args);
+            generator.emitLoad(callArguments.thisRegister(), jsUndefined());
+            generator.emitCall(returnValue.get(), realFunction.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
         }
-        generator.emitJump(end.get());
+    } else {
+        ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
+        RefPtr<RegisterID> profileHookRegister;
+        if (generator.shouldEmitProfileHooks())
+            profileHookRegister = generator.newTemporary();
+        RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
+        RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr);
+        RefPtr<RegisterID> argsRegister;
+        ArgumentListNode* args = m_args->m_listNode->m_next;
+        if (args->m_expr->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(args->m_expr)->identifier()))
+            argsRegister = generator.uncheckedRegisterForArguments();
+        else
+            argsRegister = generator.emitNode(args->m_expr);
+
+        // Function.prototype.apply ignores extra arguments, but we still
+        // need to evaluate them for side effects.
+        while ((args = args->m_next))
+            generator.emitNode(args->m_expr);
+
+        generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), profileHookRegister.get(), divot(), divotStart(), divotEnd());
     }
-    generator.emitLabel(realCall.get());
-    {
+    if (emitCallCheck) {
+        generator.emitJump(end.get());
+        generator.emitLabel(realCall.get());
         CallArguments callArguments(generator, m_args);
         generator.emitMove(callArguments.thisRegister(), base.get());
         generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
+        generator.emitLabel(end.get());
     }
-    generator.emitLabel(end.get());
     return returnValue.get();
 }
 
index 397976b..f0f6a90 100755 (executable)
@@ -248,7 +248,9 @@ sub output() {
     my $nameEntries = "${name}Values";
     $nameEntries =~ s/:/_/g;
 
+    print "\n#include \"JSCBuiltins.h\"\n";
     print "\n#include \"Lookup.h\"\n" if ($includelookup);
+
     if ($useNameSpace) {
         print "\nnamespace ${useNameSpace} {\n";
         print "\nusing namespace JSC;\n";
@@ -289,7 +291,17 @@ sub output() {
             $intrinsic = "RegExpTestIntrinsic" if ($key eq "test");
         }
 
+        if ($values[$i]{"type"} eq "Function")  {
+            my $tableHead = $name;
+            $tableHead =~ s/Table$//;
+            print " #if JSC_BUILTIN_EXISTS(" . uc($tableHead . $key) .")\n";
+            print "   { \"$key\", (($attrs[$i]) & ~Function) | Builtin, $intrinsic, (intptr_t)static_cast<BuiltinGenerator>(" . $tableHead . ucfirst($key) . "CodeGenerator), (intptr_t)$secondValue },\n";
+            print " #else\n"
+        }
         print "   { \"$key\", $attrs[$i], $intrinsic, (intptr_t)" . $firstCastStr . "($firstValue), (intptr_t)" . $secondCastStr . "($secondValue) },\n";
+        if ($values[$i]{"type"} eq "Function")  {
+            print " #endif\n"
+        }
         $i++;
     }
     print "   { 0, 0, NoIntrinsic, 0, 0 }\n";
diff --git a/Source/JavaScriptCore/generate-js-builtins b/Source/JavaScriptCore/generate-js-builtins
new file mode 100644 (file)
index 0000000..613a207
--- /dev/null
@@ -0,0 +1,304 @@
+#!/usr/bin/python
+# Copyright (C) 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.
+
+import filecmp
+import fnmatch
+import os
+import re
+import shutil
+import sys
+import datetime
+import json
+
+copyrightText = """ *
+ * 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. 
+ */\n
+"""
+
+generatorString = "/* Generated by %s do not hand edit. */\n" % os.path.basename(__file__)
+
+functionHeadRegExp = re.compile(r"function\s+\w+\s*\(.*?\)", re.MULTILINE | re.S)
+functionNameRegExp = re.compile(r"function\s+(\w+)\s*\(", re.MULTILINE | re.S)
+functionParameterFinder = re.compile(r"^function\s+(?:\w+)\s*\(((?:\s*\w+)?\s*(?:\s*,\s*\w+)*)?\)", re.MULTILINE | re.S)
+
+multilineCommentRegExp = re.compile(r"\/\*.*?\*\/", re.MULTILINE | re.S)
+singleLineCommentRegExp = re.compile(r"\/\/.*?\n", re.MULTILINE | re.S)
+
+def getCopyright(source):
+    copyrightBlock = multilineCommentRegExp.findall(source)[0]
+    copyrightBlock = copyrightBlock[:copyrightBlock.index("Redistribution")]
+    copyRightLines = []
+
+    for line in copyrightBlock.split("\n"):
+        line = line.replace("/*", "")
+        line = line.replace("*/", "")
+        line = line.replace("*", "")
+        line = line.replace("Copyright", "")
+        line = line.replace("copyright", "")
+        line = line.replace("(C)", "")
+        line = line.replace("(c)", "")
+        line = line.strip()
+        if len(line) == 0:
+            continue
+
+        copyRightLines.append(line)
+    
+    return list(set(copyRightLines))
+
+
+
+def getFunctions(source):
+
+    source = multilineCommentRegExp.sub("/**/", singleLineCommentRegExp.sub("//\n", source))
+
+    matches = [ f for f in functionHeadRegExp.finditer(source)]
+    functionBounds = []
+    start = 0
+    end = 0
+    for match in matches:
+        start = match.start()
+        if start < end:
+            continue
+        end = match.end()
+        while source[end] != '{':
+            end = end + 1
+        depth = 1
+        end = end + 1
+        while depth > 0:
+            if source[end] == '{':
+                depth = depth + 1
+            elif source[end] == '}':
+                depth = depth - 1
+            end = end + 1
+        functionBounds.append((start, end))
+
+    functions = [source[start:end].strip() for (start, end) in functionBounds]
+    result = []
+    for function in functions:
+        function = multilineCommentRegExp.sub("", function)
+        functionName = functionNameRegExp.findall(function)[0]
+        functionParameters = functionParameterFinder.findall(function)[0].split(',')
+        if len(functionParameters[0]) == 0:
+            functionParameters = []
+            
+        result.append((functionName, function, functionParameters))
+    return result
+        
+
+def generateCode(source):
+    inputFile = open(source, "r")
+    baseName = os.path.basename(source).replace(".js", "")
+    
+    source = ""
+    for line in inputFile:
+        source = source + line
+    
+    if sys.platform == "cygwin":
+        source = source.replace("\r\n", "\n")
+    return (baseName, getFunctions(source), getCopyright(source))
+
+def mangleName(object, name):
+    qName = object + "." + name
+    mangledName = ""
+    i = 0
+    while i < len(qName):
+        if qName[i] == '.':
+            mangledName = mangledName + qName[i + 1].upper()
+            i = i + 1
+        else:
+            mangledName = mangledName + qName[i]
+        i = i + 1
+    return mangledName
+
+builtins = []
+
+baseName = sys.argv[-1]
+builtin_definitions = sys.argv[1:-1]
+(output_base, _) = os.path.splitext(sys.argv[-1])
+
+copyrights = []
+for file in builtin_definitions:
+    if fnmatch.fnmatch(file, '*.js'):
+        (baseName, functions, objectCopyrights) = generateCode(file)
+        copyrights.extend(objectCopyrights)
+        builtins.append((baseName, functions))
+
+copyrights = list(set(copyrights))
+
+copyrightBody = ""
+for copyright in copyrights:
+    copyrightBody = copyrightBody +" * Copyright (C) " + copyright + "\n"
+
+builtinsHeader = open(output_base + ".h.tmp", "w")
+builtinsImplementation = open(output_base + ".cpp.tmp", "w")
+copyrightText = "/*\n" + copyrightBody + copyrightText
+builtinsHeader.write("""%s
+%s
+
+#ifndef JSCBuiltins_H
+#define JSCBuiltins_H
+
+namespace JSC {
+
+class FunctionExecutable;
+class Identifier;
+class JSGlobalObject;
+class SourceCode;
+class UnlinkedFunctionExecutable;
+class VM;
+
+FunctionExecutable* createBuiltinExecutable(VM&, UnlinkedFunctionExecutable*, const SourceCode&);
+
+""" % (generatorString, copyrightText))
+
+codeReferences = []
+
+for (objectName, functions) in builtins:
+    print("Generating bindings for the %s builtin." % objectName)
+    builtinsHeader.write("/* %s functions */\n" % objectName)
+    for (name, implementation, _) in functions:
+        mangledName = mangleName(objectName, name)
+        mangledName = mangledName[0].lower() + mangledName[1:] + "Code"
+        codeReferences.append((mangledName, name, implementation))
+        builtinsHeader.write("extern const char* s_%s;\n" % mangledName)
+        builtinsHeader.write("extern const int s_%sLength;\n" % mangledName)
+    builtinsHeader.write("\n")
+    builtinsHeader.write("#define JSC_FOREACH_%s_BUILTIN(macro) \\\n" % objectName.replace(".", "_").upper())
+    for (name, implementation, arguments) in functions:
+        mangledName = mangleName(objectName, name)
+        builtinsHeader.write("    macro(%s, %s, %d) \\\n" % (name, mangledName, len(arguments)))
+    builtinsHeader.write("\n")
+    for (name, implementation, arguments) in functions:
+        builtinsHeader.write("#define JSC_BUILTIN_%s 1\n" % mangleName(objectName, name).upper())
+    builtinsHeader.write("\n\n")
+names = []
+builtinsHeader.write("#define JSC_FOREACH_BUILTIN(macro)\\\n")
+for (codeReference, functionName, source) in codeReferences:
+    builtinsHeader.write("    macro(%s, %s, s_%sLength) \\\n" % (codeReference, functionName, codeReference))
+    names.append(functionName)
+
+builtinsHeader.write("\n\n")
+builtinsHeader.write("#define JSC_FOREACH_BUILTIN_FUNCTION_NAME(macro) \\\n")
+for name in sorted(set(names)):
+    builtinsHeader.write("    macro(%s) \\\n" % name)
+builtinsHeader.write("""
+
+#define JSC_DECLARE_BUILTIN_GENERATOR(codeName, functionName, argumentCount) \\
+    FunctionExecutable* codeName##Generator(VM&);
+
+JSC_FOREACH_BUILTIN(JSC_DECLARE_BUILTIN_GENERATOR)
+#undef JSC_DECLARE_BUILTIN_GENERATOR
+
+#define JSC_BUILTIN_EXISTS(name) defined JSC_BUILTIN_ ## name
+
+}
+
+#endif
+
+""")
+
+builtinsImplementation.write("""%s
+%s
+
+#include "config.h"
+
+#include "JSCBuiltins.h"
+
+#include "BuiltinExecutables.h"
+#include "Executable.h"
+#include "JSCellInlines.h"
+#include "VM.h"
+
+namespace JSC {
+
+"""  % (generatorString, copyrightText))
+
+for (codeReference, name, source) in codeReferences:
+    source = "(function " + source[source.index("("):] + ")"
+    lines = json.dumps(source)[1:-1].split("\\n")
+    sourceLength = len(source)
+    source = ""
+    for line in lines:
+        source = source + ("    \"%s\\n\" \\\n" % line)
+    builtinsImplementation.write("const char* s_%s =\n%s;\n\n" % (codeReference, source))
+    builtinsImplementation.write("const int s_%sLength = %d;\n\n" % (codeReference, sourceLength + 1)) # + 1 for \n
+
+builtinsImplementation.write("""
+FunctionExecutable* createBuiltinExecutable(VM& vm, UnlinkedFunctionExecutable* unlinkedExecutable, const SourceCode& source)
+{
+    unsigned lineCount = unlinkedExecutable->lineCount();
+    unsigned startColumn = 1;
+    unsigned sourceLength = unlinkedExecutable->sourceLength();
+    bool endColumnIsOnStartLine = !lineCount;
+    unsigned endColumnExcludingBraces = unlinkedExecutable->unlinkedBodyEndColumn() + (endColumnIsOnStartLine ? 0 : 1);
+    unsigned startOffset = unlinkedExecutable->startOffset();
+    unsigned startOffsetExcludingOpenBrace = startOffset + 1;
+    unsigned endOffsetExcludingCloseBrace = startOffset + sourceLength - 1;
+    SourceCode bodySource(source.provider(), startOffsetExcludingOpenBrace, endOffsetExcludingCloseBrace, 0, startColumn);
+    return FunctionExecutable::create(vm, bodySource, unlinkedExecutable, 0, lineCount, startColumn, endColumnExcludingBraces, false);
+}
+
+#define JSC_DEFINE_BUILTIN_GENERATOR(codeName, functionName, argumentCount) \\
+FunctionExecutable* codeName##Generator(VM& vm) \\
+{ \\
+    return createBuiltinExecutable(vm, vm.builtinExecutables()->codeName##Executable(), vm.builtinExecutables()->codeName##Source()); \\
+}
+
+JSC_FOREACH_BUILTIN(JSC_DEFINE_BUILTIN_GENERATOR)
+#undef JSC_DEFINE_BUILTIN_GENERATOR
+}
+
+""")
+
+builtinsHeader.close()
+builtinsImplementation.close()
+
+if (not os.path.exists(output_base + ".h")) or (not filecmp.cmp(output_base + ".h.tmp", output_base + ".h", shallow=False)):
+    os.rename(output_base + ".h.tmp", output_base + ".h")
+else:
+    os.remove(output_base + ".h.tmp")
+
+if (not os.path.exists(output_base + ".cpp")) or (not filecmp.cmp(output_base + ".cpp.tmp", output_base + ".cpp", shallow=False)):
+    os.rename(output_base + ".cpp.tmp", output_base + ".cpp")
+else:
+    os.remove(output_base + ".cpp.tmp")
index 2ca3e97..30cad2a 100644 (file)
@@ -43,7 +43,7 @@ namespace JSC {
             , m_interpreter(callFrame->interpreter())
             , m_entryScope(callFrame->vm(), function->scope()->globalObject())
         {
-            ASSERT(!function->isHostFunction());
+            ASSERT(!function->isHostFunctionNonInline());
             if (callFrame->vm().isSafeToRecurse()) {
                 m_arguments.resize(argumentCount);
                 m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, &m_protoCallFrame, function, argumentCount + 1, function->scope(), m_arguments.data());
index 8ec1fd3..46a7c76 100644 (file)
@@ -888,9 +888,9 @@ ExpressionNode* ASTBuilder::makeFunctionCallNode(const JSTokenLocation& location
     ASSERT(func->isDotAccessorNode());
     DotAccessorNode* dot = static_cast<DotAccessorNode*>(func);
     FunctionCallDotNode* node;
-    if (dot->identifier() == m_vm->propertyNames->call)
+    if (dot->identifier() == m_vm->propertyNames->call || dot->identifier() == m_vm->propertyNames->callPrivateName)
         node = new (m_vm) CallFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divotStart, divotEnd);
-    else if (dot->identifier() == m_vm->propertyNames->apply)
+    else if (dot->identifier() == m_vm->propertyNames->apply || dot->identifier() == m_vm->propertyNames->applyPrivateName)
         node = new (m_vm) ApplyFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divotStart, divotEnd);
     else
         node = new (m_vm) FunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divotStart, divotEnd);
index 4414bff..ead5022 100644 (file)
@@ -91,6 +91,7 @@ enum CharacterType {
 
     // Other types (only one so far)
     CharacterWhiteSpace,
+    CharacterPrivateIdentifierStart
 };
 
 // 256 Latin-1 codes
@@ -159,7 +160,7 @@ static const unsigned short typesOfLatin1Characters[256] = {
 /*  61 - =                  */ CharacterEqual,
 /*  62 - >                  */ CharacterGreater,
 /*  63 - ?                  */ CharacterQuestion,
-/*  64 - @                  */ CharacterInvalid,
+/*  64 - @                  */ CharacterPrivateIdentifierStart,
 /*  65 - A                  */ CharacterIdentifierStart,
 /*  66 - B                  */ CharacterIdentifierStart,
 /*  67 - C                  */ CharacterIdentifierStart,
@@ -487,9 +488,10 @@ static const LChar singleCharacterEscapeValuesForASCII[128] = {
 };
 
 template <typename T>
-Lexer<T>::Lexer(VM* vm)
+Lexer<T>::Lexer(VM* vm, JSParserStrictness strictness)
     : m_isReparsing(false)
     , m_vm(vm)
+    , m_parsingBuiltinFunction(strictness == JSParseBuiltin)
 {
 }
 
@@ -754,7 +756,27 @@ inline void Lexer<T>::record16(int c)
     ASSERT(c <= static_cast<int>(USHRT_MAX));
     m_buffer16.append(static_cast<UChar>(c));
 }
-
+    
+#if !ASSERT_DISABLED
+bool isSafeBuiltinIdentifier(VM& vm, const Identifier* ident)
+{
+    if (!ident)
+        return true;
+    /* Just block any use of suspicious identifiers.  This is intended to
+     * be used as a safety net while implementing builtins.
+     */
+    if (*ident == vm.propertyNames->call)
+        return false;
+    if (*ident == vm.propertyNames->apply)
+        return false;
+    if (*ident == vm.propertyNames->eval)
+        return false;
+    if (*ident == vm.propertyNames->Function)
+        return false;
+    return true;
+}
+#endif
+    
 template <>
 template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<LChar>::parseIdentifier(JSTokenData* tokenData, unsigned lexerFlags, bool strictMode)
 {
@@ -766,7 +788,11 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<LChar>::p
             return keyword == RESERVED_IF_STRICT && !strictMode ? IDENT : keyword;
         }
     }
-
+    
+    bool isPrivateName = m_current == '@' && m_parsingBuiltinFunction;
+    if (isPrivateName)
+        shift();
+    
     const LChar* identifierStart = currentSourcePtr();
     unsigned identifierLineStart = currentLineStartOffset();
     
@@ -780,15 +806,26 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<LChar>::p
 
     const Identifier* ident = 0;
     
-    if (shouldCreateIdentifier) {
+    if (shouldCreateIdentifier || m_parsingBuiltinFunction) {
         int identifierLength = currentSourcePtr() - identifierStart;
         ident = makeIdentifier(identifierStart, identifierLength);
-
+        if (m_parsingBuiltinFunction) {
+            if (!isSafeBuiltinIdentifier(*m_vm, ident) && !isPrivateName) {
+                m_lexErrorMessage = makeString("The use of '", ident->string(), "' is disallowed in builtin functions.");
+                return ERRORTOK;
+            }
+            if (isPrivateName)
+                ident = m_vm->propertyNames->getPrivateName(*ident);
+            else if (*ident == m_vm->propertyNames->undefinedKeyword)
+                tokenData->ident = &m_vm->propertyNames->undefinedPrivateName;
+            if (!ident)
+                return INVALID_PRIVATE_NAME_ERRORTOK;
+        }
         tokenData->ident = ident;
     } else
         tokenData->ident = 0;
 
-    if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords))) {
+    if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords)) && !isPrivateName) {
         ASSERT(shouldCreateIdentifier);
         if (remaining < maxTokenLength) {
             const HashEntry* entry = m_vm->keywords->getKeyword(*ident);
@@ -815,6 +852,10 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::p
             return keyword == RESERVED_IF_STRICT && !strictMode ? IDENT : keyword;
         }
     }
+    
+    bool isPrivateName = m_current == '@' && m_parsingBuiltinFunction;
+    if (isPrivateName)
+        shift();
 
     const UChar* identifierStart = currentSourcePtr();
     int identifierLineStart = currentLineStartOffset();
@@ -827,6 +868,7 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::p
     }
     
     if (UNLIKELY(m_current == '\\')) {
+        ASSERT(!isPrivateName);
         setOffsetFromSourcePtr(identifierStart, identifierLineStart);
         return parseIdentifierSlowCase<shouldCreateIdentifier>(tokenData, lexerFlags, strictMode);
     }
@@ -838,18 +880,29 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::p
 
     const Identifier* ident = 0;
     
-    if (shouldCreateIdentifier) {
+    if (shouldCreateIdentifier || m_parsingBuiltinFunction) {
         int identifierLength = currentSourcePtr() - identifierStart;
         if (isAll8Bit)
             ident = makeIdentifierLCharFromUChar(identifierStart, identifierLength);
         else
             ident = makeIdentifier(identifierStart, identifierLength);
-        
+        if (m_parsingBuiltinFunction) {
+            if (!isSafeBuiltinIdentifier(*m_vm, ident) && !isPrivateName) {
+                m_lexErrorMessage = makeString("The use of '", ident->string(), "' is disallowed in builtin functions.");
+                return ERRORTOK;
+            }
+            if (isPrivateName)
+                ident = m_vm->propertyNames->getPrivateName(*ident);
+            else if (*ident == m_vm->propertyNames->undefinedKeyword)
+                tokenData->ident = &m_vm->propertyNames->undefinedPrivateName;
+            if (!ident)
+                return INVALID_PRIVATE_NAME_ERRORTOK;
+        }
         tokenData->ident = ident;
     } else
         tokenData->ident = 0;
     
-    if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords))) {
+    if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords)) && !isPrivateName) {
         ASSERT(shouldCreateIdentifier);
         if (remaining < maxTokenLength) {
             const HashEntry* entry = m_vm->keywords->getKeyword(*ident);
@@ -1659,6 +1712,7 @@ inNumberAfterDecimalPoint:
         ASSERT(isIdentStart(m_current));
         FALLTHROUGH;
     case CharacterBackSlash:
+        parseIdent:
         if (lexerFlags & LexexFlagsDontBuildKeywords)
             token = parseIdentifier<false>(tokenData, lexerFlags, strictMode);
         else
@@ -1671,6 +1725,11 @@ inNumberAfterDecimalPoint:
         m_terminator = true;
         m_lineStart = m_code;
         goto start;
+    case CharacterPrivateIdentifierStart:
+        if (m_parsingBuiltinFunction)
+            goto parseIdent;
+
+        FALLTHROUGH;
     case CharacterInvalid:
         m_lexErrorMessage = invalidCharacterMessage();
         token = ERRORTOK;
index 2e922bb..10aecfc 100644 (file)
@@ -71,7 +71,7 @@ class Lexer {
     WTF_MAKE_FAST_ALLOCATED;
 
 public:
-    Lexer(VM*);
+    Lexer(VM*, JSParserStrictness);
     ~Lexer();
 
     // Character manipulation functions.
@@ -237,6 +237,7 @@ private:
     IdentifierArena* m_arena;
 
     VM* m_vm;
+    bool m_parsingBuiltinFunction;
 };
 
 template <>
@@ -335,6 +336,12 @@ ALWAYS_INLINE const Identifier* Lexer<T>::makeLCharIdentifier(const UChar* chara
     return &m_arena->makeIdentifierLCharFromUChar(m_vm, characters, length);
 }
 
+#if ASSERT_DISABLED
+ALWAYS_INLINE bool isSafeBuiltinIdentifier(VM&, const Identifier*) { return true; }
+#else
+bool isSafeBuiltinIdentifier(VM&, const Identifier*);
+#endif
+
 template <typename T>
 ALWAYS_INLINE JSTokenType Lexer<T>::lexExpectIdentifier(JSToken* tokenRecord, unsigned lexerFlags, bool strictMode)
 {
@@ -370,10 +377,15 @@ ALWAYS_INLINE JSTokenType Lexer<T>::lexExpectIdentifier(JSToken* tokenRecord, un
     ASSERT(currentOffset() >= currentLineStartOffset());
 
     // Create the identifier if needed
-    if (lexerFlags & LexexFlagsDontBuildKeywords)
+    if (lexerFlags & LexexFlagsDontBuildKeywords
+#if !ASSERT_DISABLED
+        && !m_parsingBuiltinFunction
+#endif
+        )
         tokenData->ident = 0;
     else
         tokenData->ident = makeLCharIdentifier(start, ptr - start);
+
     tokenLocation->line = m_lineNumber;
     tokenLocation->lineStartOffset = currentLineStartOffset();
     tokenLocation->startOffset = offsetFromSourcePtr(start);
@@ -381,6 +393,13 @@ ALWAYS_INLINE JSTokenType Lexer<T>::lexExpectIdentifier(JSToken* tokenRecord, un
     ASSERT(tokenLocation->startOffset >= tokenLocation->lineStartOffset);
     tokenRecord->m_startPosition = startPosition;
     tokenRecord->m_endPosition = currentPosition();
+#if !ASSERT_DISABLED
+    if (m_parsingBuiltinFunction) {
+        if (!isSafeBuiltinIdentifier(*m_vm, tokenData->ident))
+            return ERRORTOK;
+    }
+#endif
+
     m_lastToken = IDENT;
     return IDENT;
     
index 134c1d1..2da148f 100644 (file)
@@ -132,6 +132,12 @@ PassRefPtr<ProgramNode> ProgramNode::create(VM* vm, const JSTokenLocation& start
     return node.release();
 }
 
+
+void ProgramNode::setClosedVariables(const Vector<RefPtr<StringImpl>>&& closedVariables)
+{
+    m_closedVariables = std::move(closedVariables);
+}
+
 // ------------------------------ EvalNode -----------------------------
 
 inline EvalNode::EvalNode(VM* vm, const JSTokenLocation& startLocation, const JSTokenLocation& endLocation, unsigned endColumn, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
index 783282b..665cc84 100644 (file)
@@ -1431,6 +1431,7 @@ namespace JSC {
         bool needsActivation() const { return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); }
         bool hasCapturedVariables() const { return !!m_capturedVariables.size(); }
         size_t capturedVariableCount() const { return m_capturedVariables.size(); }
+        const IdentifierSet& capturedVariables() const { return m_capturedVariables; }
         bool captures(const Identifier& ident) { return m_capturedVariables.contains(ident.impl()); }
 
         VarStack& varStack() { return m_varStack; }
@@ -1446,6 +1447,8 @@ namespace JSC {
         StatementNode* singleStatement() const;
 
         void emitStatementsBytecode(BytecodeGenerator&, RegisterID* destination);
+        
+        void setClosedVariables(const Vector<RefPtr<StringImpl>>&&) { }
 
     protected:
         void setSource(const SourceCode& source) { m_source = source; }
@@ -1475,11 +1478,13 @@ namespace JSC {
 
         static const bool scopeIsFunction = false;
 
+        void setClosedVariables(const Vector<RefPtr<StringImpl>>&&);
+        const Vector<RefPtr<StringImpl>>& closedVariables() const { return m_closedVariables; }
     private:
         ProgramNode(VM*, const JSTokenLocation& start, const JSTokenLocation& end, unsigned startColumn, unsigned endColumn, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         virtual void emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
-
+        Vector<RefPtr<StringImpl>> m_closedVariables;
         unsigned m_startColumn;
         unsigned m_endColumn;
     };
index 58e72f4..749928b 100644 (file)
@@ -205,8 +205,9 @@ Parser<LexerType>::Parser(VM* vm, const SourceCode& source, FunctionParameters*
     , m_lastIdentifier(0)
     , m_lastFunctionName(nullptr)
     , m_sourceElements(0)
+    , m_parsingBuiltin(strictness == JSParseBuiltin)
 {
-    m_lexer = adoptPtr(new LexerType(vm));
+    m_lexer = adoptPtr(new LexerType(vm, strictness));
     m_arena = m_vm->parserArena.get();
     m_lexer->setCode(source, m_arena);
     m_token.m_location.line = source.firstLine();
@@ -271,6 +272,7 @@ String Parser<LexerType>::parseInner()
     IdentifierSet capturedVariables;
     bool modifiedParameter = false;
     scope->getCapturedVariables(capturedVariables, modifiedParameter);
+    
     CodeFeatures features = context.features();
     if (scope->strictMode())
         features |= StrictModeFeature;
@@ -278,21 +280,36 @@ String Parser<LexerType>::parseInner()
         features |= ShadowsArgumentsFeature;
     if (modifiedParameter)
         features |= ModifiedParameterFeature;
-
+    
+    Vector<RefPtr<StringImpl>> closedVariables;
+    if (m_parsingBuiltin) {
+        RELEASE_ASSERT(!capturedVariables.size());
+        IdentifierSet usedVariables;
+        scope->getUsedVariables(usedVariables);
+        for (const auto& variable : usedVariables) {
+            if (scope->hasDeclaredVariable(Identifier(m_vm, variable.get())))
+                continue;
+            
+            if (scope->hasDeclaredParameter(Identifier(m_vm, variable.get())))
+                continue;
+            closedVariables.append(variable);
+        }
+    }
     didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
-        context.numConstants(), capturedVariables);
+        context.numConstants(), capturedVariables, std::move(closedVariables));
 
     return parseError;
 }
 
 template <typename LexerType>
 void Parser<LexerType>::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack, 
-    ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int numConstants, IdentifierSet& capturedVars)
+    ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int numConstants, IdentifierSet& capturedVars, const Vector<RefPtr<StringImpl>>&& closedVariables)
 {
     m_sourceElements = sourceElements;
     m_varDeclarations = varStack;
     m_funcDeclarations = funcStack;
     m_capturedVariables.swap(capturedVars);
+    m_closedVariables = closedVariables;
     m_features = features;
     m_numConstants = numConstants;
 }
@@ -2362,6 +2379,10 @@ template <typename LexerType> void Parser<LexerType>::printUnexpectedTokenText(W
     case RESERVED:
         out.print("Unexpected use of reserved word '", getToken(), "'");
         return;
+
+    case INVALID_PRIVATE_NAME_ERRORTOK:
+        out.print("Invalid private name '", getToken(), "'");
+        return;
             
     case IDENT:
         out.print("Unexpected identifier '", getToken(), "'");
index b698ef9..d6988e7 100644 (file)
@@ -259,6 +259,10 @@ struct Scope {
         return isValidStrictMode ? BindingSucceeded : StrictBindingFailed;
     }
 
+    void getUsedVariables(IdentifierSet& usedVariables)
+    {
+        usedVariables.swap(m_usedVariables);
+    }
 
     void useVariable(const Identifier* ident, bool isEval)
     {
@@ -414,6 +418,7 @@ public:
     PassRefPtr<ParsedNode> parse(ParserError&);
 
     JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); }
+    const Vector<RefPtr<StringImpl>>&& closedVariables() { return std::move(m_closedVariables); }
 
 private:
     struct AllowInOverride {
@@ -540,7 +545,7 @@ private:
     String parseInner();
 
     void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, 
-        ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures, int, IdentifierSet&);
+        ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures, int, IdentifierSet&, const Vector<RefPtr<StringImpl>>&&);
 
     // Used to determine type of error to report.
     bool isFunctionBodyNode(ScopeNode*) { return false; }
@@ -840,9 +845,11 @@ private:
     const Identifier* m_lastFunctionName;
     RefPtr<SourceProviderCache> m_functionCache;
     SourceElements* m_sourceElements;
+    bool m_parsingBuiltin;
     ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations;
     ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
     IdentifierSet m_capturedVariables;
+    Vector<RefPtr<StringImpl>> m_closedVariables;
     CodeFeatures m_features;
     int m_numConstants;
     
@@ -957,6 +964,12 @@ PassRefPtr<ParsedNode> parse(VM* vm, const SourceCode& source, FunctionParameter
         RefPtr<ParsedNode> result = parser.parse<ParsedNode>(error);
         if (positionBeforeLastNewline)
             *positionBeforeLastNewline = parser.positionBeforeLastNewline();
+        if (strictness == JSParseBuiltin) {
+            if (!result)
+                WTF::dataLog("Error compiling builtin: ", error.m_message, "\n");
+            RELEASE_ASSERT(result);
+            result->setClosedVariables(std::move(parser.closedVariables()));
+        }
         return result.release();
     }
     Parser<Lexer<UChar>> parser(vm, source, parameters, name, strictness, parserMode);
index 57c9ffb..9314b19 100644 (file)
@@ -31,7 +31,7 @@
 
 namespace JSC {
 
-enum JSParserStrictness { JSParseNormal, JSParseStrict };
+enum JSParserStrictness { JSParseNormal, JSParseBuiltin, JSParseStrict };
 enum JSParserMode { JSParseProgramCode, JSParseFunctionCode };
 
 enum ProfilerMode { ProfilerOff, ProfilerOn };
index 82a2663..8c87ad9 100644 (file)
@@ -149,6 +149,7 @@ enum JSTokenType {
     INVALID_NUMERIC_LITERAL_ERRORTOK = 7 | ErrorTokenFlag,
     UNTERMINATED_STRING_LITERAL_ERRORTOK = 8 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
     INVALID_STRING_LITERAL_ERRORTOK = 9 | ErrorTokenFlag,
+    INVALID_PRIVATE_NAME_ERRORTOK = 10 | ErrorTokenFlag
 };
 
 struct JSTextPosition {
index 13d783c..c55cc1e 100644 (file)
@@ -56,7 +56,6 @@ 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*);
@@ -955,69 +954,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
     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().toThis(exec, StrictMode).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<JSFunction*>(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().toThis(exec, StrictMode).toObject(exec);
index 3caee32..6de1044 100644 (file)
@@ -144,24 +144,26 @@ UnlinkedFunctionExecutable* CodeCache::getFunctionExecutableFromGlobalCode(VM& v
     JSTextPosition positionBeforeLastNewline;
     RefPtr<ProgramNode> program = parse<ProgramNode>(&vm, source, 0, Identifier(), JSParseNormal, JSParseProgramCode, error, &positionBeforeLastNewline);
     if (!program) {
-        ASSERT(error.m_type != ParserError::ErrorNone);
+        RELEASE_ASSERT(error.m_type != ParserError::ErrorNone);
         m_sourceCode.remove(addResult.iterator);
         return 0;
     }
 
     // This function assumes an input string that would result in a single anonymous function expression.
     StatementNode* exprStatement = program->singleStatement();
-    ASSERT(exprStatement);
-    ASSERT(exprStatement->isExprStatement());
+    RELEASE_ASSERT(exprStatement);
+    RELEASE_ASSERT(exprStatement->isExprStatement());
     ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
-    ASSERT(funcExpr);
+    RELEASE_ASSERT(funcExpr);
     RELEASE_ASSERT(funcExpr->isFuncExprNode());
     FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
+    RELEASE_ASSERT(!program->hasCapturedVariables());
+    
     body->setEndPosition(positionBeforeLastNewline);
-    ASSERT(body);
-    ASSERT(body->ident().isNull());
+    RELEASE_ASSERT(body);
+    RELEASE_ASSERT(body->ident().isNull());
 
-    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, body, true);
+    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, body, true, UnlinkedNormalFunction);
     functionExecutable->m_nameValue.set(vm, functionExecutable, jsString(&vm, name.string()));
 
     addResult.iterator->value = SourceCodeValue(vm, functionExecutable, m_sourceCode.age());
index 3f5c645..56df345 100644 (file)
 #include "config.h"
 #include "CommonIdentifiers.h"
 
+#include "BuiltinNames.h"
+#include "JSCBuiltins.h"
 #include "PrivateName.h"
 
 namespace JSC {
 
 #define INITIALIZE_PROPERTY_NAME(name) , name(vm, #name)
 #define INITIALIZE_KEYWORD(name) , name##Keyword(vm, #name)
-#define INITIALIZE_PRIVATE_NAME(name) , name##PrivateName(Identifier::from(PrivateName()))
+#define INITIALIZE_PRIVATE_NAME(name) , name##PrivateName(m_builtinNames->name##PrivateName())
 
 CommonIdentifiers::CommonIdentifiers(VM* vm)
     : nullIdentifier()
@@ -35,11 +37,26 @@ CommonIdentifiers::CommonIdentifiers(VM* vm)
     , underscoreProto(vm, "__proto__")
     , thisIdentifier(vm, "this")
     , useStrictIdentifier(vm, "use strict")
-    , hasNextIdentifier(vm, "hasNext")
+    , m_builtinNames(new BuiltinNames(vm, this))
     JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(INITIALIZE_KEYWORD)
     JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME)
     JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PRIVATE_NAME)
 {
 }
 
+CommonIdentifiers::~CommonIdentifiers()
+{
+}
+
+const Identifier* CommonIdentifiers::getPrivateName(const Identifier& ident) const
+{
+    return m_builtinNames->getPrivateName(ident);
+}
+    
+Identifier CommonIdentifiers::getPublicName(const Identifier& ident) const
+{
+    return m_builtinNames->getPublicName(ident);
+}
+
+
 } // namespace JSC
index 17a7188..e2ea2b3 100644 (file)
     macro(yield)
 
 #define JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \
+    macro(apply) \
+    macro(call) \
     macro(iterator) \
     macro(iteratorNext) \
     macro(resolve) \
     macro(index) \
     macro(values) \
     macro(deferred) \
-    macro(countdownHolder)
+    macro(countdownHolder) \
+    macro(Object) \
+    macro(TypeError) \
+    macro(undefined)
 
 namespace JSC {
-
+    
+    class BuiltinNames;
+    
     class CommonIdentifiers {
         WTF_MAKE_NONCOPYABLE(CommonIdentifiers); WTF_MAKE_FAST_ALLOCATED;
     private:
         CommonIdentifiers(VM*);
+        ~CommonIdentifiers();
         friend class VM;
-
+        
     public:
+        const BuiltinNames& builtinNames() const { return *m_builtinNames; }
         const Identifier nullIdentifier;
         const Identifier emptyIdentifier;
         const Identifier underscoreProto;
         const Identifier thisIdentifier;
         const Identifier useStrictIdentifier;
-        const Identifier hasNextIdentifier;
+    private:
+        std::unique_ptr<BuiltinNames> m_builtinNames;
+
+    public:
         
 #define JSC_IDENTIFIER_DECLARE_KEYWORD_NAME_GLOBAL(name) const Identifier name##Keyword;
         JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(JSC_IDENTIFIER_DECLARE_KEYWORD_NAME_GLOBAL)
@@ -246,6 +258,9 @@ namespace JSC {
 #define JSC_IDENTIFIER_DECLARE_PRIVATE_PROPERTY_NAME_GLOBAL(name) const Identifier name##PrivateName;
         JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(JSC_IDENTIFIER_DECLARE_PRIVATE_PROPERTY_NAME_GLOBAL)
 #undef JSC_IDENTIFIER_DECLARE_PRIVATE_PROPERTY_NAME_GLOBAL
+        
+        const Identifier* getPrivateName(const Identifier&) const;
+        Identifier getPublicName(const Identifier&) const;
     };
 
 } // namespace JSC
index 5563be6..2b61183 100644 (file)
@@ -81,6 +81,11 @@ JSObject* createStackOverflowError(JSGlobalObject* globalObject)
 
 JSObject* createUndefinedVariableError(ExecState* exec, const Identifier& ident)
 {
+    
+    if (ident.impl()->isEmptyUnique()) {
+        String message(makeString("Can't find private variable: @", exec->propertyNames().getPublicName(ident).string()));
+        return createReferenceError(exec, message);
+    }
     String message(makeString("Can't find variable: ", ident.string()));
     return createReferenceError(exec, message);
 }
index 57e6ae3..fb05e5a 100644 (file)
@@ -484,7 +484,7 @@ public:
 
     void clearCode();
 
-    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
+    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false); }
 
     unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); }
     unsigned numberOfFunctionDecls() { return m_unlinkedEvalCodeBlock->numberOfFunctionDecls(); }
@@ -540,7 +540,7 @@ public:
 
     void clearCode();
 
-    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false); }
+    ExecutableInfo executableInfo() const { return ExecutableInfo(needsActivation(), usesEval(), isStrictMode(), false, false); }
 
 private:
     friend class ScriptExecutable;
@@ -630,6 +630,7 @@ public:
     }
         
     FunctionMode functionMode() { return m_unlinkedExecutable->functionMode(); }
+    bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); }
     const Identifier& name() { return m_unlinkedExecutable->name(); }
     const Identifier& inferredName() { return m_unlinkedExecutable->inferredName(); }
     JSString* nameValue() const { return m_unlinkedExecutable->nameValue(); }
@@ -677,14 +678,6 @@ private:
     bool m_didParseForTheFirstTime;
 };
 
-inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
-{
-    JSFunction* function = jsCast<JSFunction*>(getJSFunction(value));
-    if (!function || !function->isHostFunction())
-        return false;
-    return function->nativeFunction() == nativeFunction;
-}
-
 inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
 {
     switch (executable->structure()->typeInfo().type()) {
index 36cb137..a623cf3 100644 (file)
@@ -108,7 +108,7 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
     JSValue thisValue = exec->hostThisValue();
     if (thisValue.inherits(JSFunction::info())) {
         JSFunction* function = jsCast<JSFunction*>(thisValue);
-        if (function->isHostFunction())
+        if (function->isHostOrBuiltinFunction())
             return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n    [native code]\n}"));
         FunctionExecutable* executable = function->jsExecutable();
         String sourceString = executable->source().toString();
index e177194..ca4c014 100644 (file)
@@ -58,7 +58,7 @@ void JSActivation::visitChildren(JSCell* cell, SlotVisitor& visitor)
 
 inline bool JSActivation::symbolTableGet(PropertyName propertyName, PropertySlot& slot)
 {
-    SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.publicName());
+    SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.uid());
     if (entry.isNull())
         return false;
 
@@ -72,7 +72,7 @@ inline bool JSActivation::symbolTableGet(PropertyName propertyName, PropertySlot
 
 inline bool JSActivation::symbolTableGet(PropertyName propertyName, PropertyDescriptor& descriptor)
 {
-    SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.publicName());
+    SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.uid());
     if (entry.isNull())
         return false;
 
@@ -89,7 +89,7 @@ inline bool JSActivation::symbolTablePut(ExecState* exec, PropertyName propertyN
     VM& vm = exec->vm();
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
     
-    SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.publicName());
+    SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.uid());
     if (entry.isNull())
         return false;
     if (entry.isReadOnly()) {
@@ -136,7 +136,7 @@ inline bool JSActivation::symbolTablePutWithAttributes(VM& vm, PropertyName prop
     WriteBarrierBase<Unknown>* reg;
     {
         ConcurrentJITLocker locker(symbolTable()->m_lock);
-        SymbolTable::Map::iterator iter = symbolTable()->find(locker, propertyName.publicName());
+        SymbolTable::Map::iterator iter = symbolTable()->find(locker, propertyName.uid());
         if (iter == symbolTable()->end(locker))
             return false;
         SymbolTableEntry& entry = iter->value;
index bdc45c5..5ac84ed 100644 (file)
@@ -33,7 +33,8 @@
 #include "FunctionPrototype.h"
 #include "GetterSetter.h"
 #include "JSArray.h"
-#include "JSBoundFunction.h" 
+#include "JSBoundFunction.h"
+#include "JSFunctionInlines.h"
 #include "JSGlobalObject.h"
 #include "JSNameScope.h" 
 #include "JSNotAnObject.h"
@@ -119,6 +120,14 @@ void JSFunction::addNameScopeIfNeeded(VM& vm)
     m_scope.set(vm, this, JSNameScope::create(vm, m_scope->globalObject(), executable->name(), this, ReadOnly | DontDelete, m_scope.get()));
 }
 
+JSFunction* JSFunction::createBuiltinFunction(VM& vm, FunctionExecutable* executable, JSGlobalObject* globalObject)
+{
+    JSFunction* function = create(vm, executable, globalObject);
+    function->putDirect(vm, vm.propertyNames->name, jsString(&vm, executable->name().string()), DontDelete | ReadOnly | DontEnum);
+    function->putDirect(vm, vm.propertyNames->length, jsNumber(executable->parameterCount()), DontDelete | ReadOnly | DontEnum);
+    return function;
+}
+
 ObjectAllocationProfile* JSFunction::createAllocationProfile(ExecState* exec, size_t inlineCapacity)
 {
     VM& vm = exec->vm();
@@ -152,7 +161,7 @@ const String JSFunction::calculatedDisplayName(ExecState* exec)
         return explicitName;
     
     const String actualName = name(exec);
-    if (!actualName.isEmpty() || isHostFunction())
+    if (!actualName.isEmpty() || isHostOrBuiltinFunction())
         return actualName;
     
     return jsExecutable()->inferredName().string();
@@ -160,10 +169,20 @@ const String JSFunction::calculatedDisplayName(ExecState* exec)
 
 const SourceCode* JSFunction::sourceCode() const
 {
-    if (isHostFunction())
+    if (isHostOrBuiltinFunction())
         return 0;
     return &jsExecutable()->source();
 }
+    
+bool JSFunction::isHostOrBuiltinFunction() const
+{
+    return isHostFunction() || isBuiltinFunction();
+}
+
+bool JSFunction::isBuiltinFunction() const
+{
+    return !isHostFunction() && jsExecutable()->isBuiltinFunction();
+}
 
 void JSFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
@@ -287,7 +306,7 @@ EncodedJSValue JSFunction::callerGetter(ExecState* exec, JSObject* slotBase, Enc
     if (!caller.isObject() || !asObject(caller)->inherits(JSFunction::info()))
         return JSValue::encode(caller);
     JSFunction* function = jsCast<JSFunction*>(caller);
-    if (function->isHostFunction() || !function->jsExecutable()->isStrictMode())
+    if (function->isHostOrBuiltinFunction() || !function->jsExecutable()->isStrictMode())
         return JSValue::encode(caller);
     return JSValue::encode(throwTypeError(exec, ASCIILiteral("Function.caller used to retrieve strict caller")));
 }
@@ -309,7 +328,7 @@ EncodedJSValue JSFunction::nameGetter(ExecState*, JSObject* slotBase, EncodedJSV
 bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
 {
     JSFunction* thisObject = jsCast<JSFunction*>(object);
-    if (thisObject->isHostFunction())
+    if (thisObject->isHostOrBuiltinFunction())
         return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
 
     if (propertyName == exec->propertyNames().prototype) {
@@ -371,7 +390,7 @@ bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyN
 void JSFunction::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
     JSFunction* thisObject = jsCast<JSFunction*>(object);
-    if (!thisObject->isHostFunction() && (mode == IncludeDontEnumProperties)) {
+    if (!thisObject->isHostOrBuiltinFunction() && (mode == IncludeDontEnumProperties)) {
         // Make sure prototype has been reified.
         PropertySlot slot(thisObject);
         thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, exec->propertyNames().prototype, slot);
@@ -387,7 +406,7 @@ void JSFunction::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec,
 void JSFunction::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
 {
     JSFunction* thisObject = jsCast<JSFunction*>(cell);
-    if (thisObject->isHostFunction()) {
+    if (thisObject->isHostOrBuiltinFunction()) {
         Base::put(thisObject, exec, propertyName, value, slot);
         return;
     }
@@ -435,7 +454,7 @@ bool JSFunction::deleteProperty(JSCell* cell, ExecState* exec, PropertyName prop
 bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException)
 {
     JSFunction* thisObject = jsCast<JSFunction*>(object);
-    if (thisObject->isHostFunction())
+    if (thisObject->isHostOrBuiltinFunction())
         return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
 
     if (propertyName == exec->propertyNames().prototype) {
index a248e16..f7b7f16 100644 (file)
@@ -68,6 +68,8 @@ namespace JSC {
             return function;
         }
         
+        static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*);
+        
         static void destroy(JSCell*);
         
         JS_EXPORT_PRIVATE String name(ExecState*);
@@ -146,6 +148,10 @@ namespace JSC {
             return m_allocationProfileWatchpoint;
         }
 
+        bool isHostOrBuiltinFunction() const;
+        bool isBuiltinFunction() const;
+        JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const;
+
     protected:
         const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
 
@@ -170,8 +176,6 @@ namespace JSC {
     private:
         friend class LLIntOffsetsExtractor;
         
-        JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const;
-
         static EncodedJSValue argumentsGetter(ExecState*, JSObject*, EncodedJSValue, PropertyName);
         static EncodedJSValue callerGetter(ExecState*, JSObject*, EncodedJSValue, PropertyName);
         static EncodedJSValue lengthGetter(ExecState*, JSObject*, EncodedJSValue, PropertyName);
index fe4e114..69f0d4f 100644 (file)
@@ -53,16 +53,24 @@ inline bool JSFunction::isHostFunction() const
 
 inline NativeFunction JSFunction::nativeFunction()
 {
-    ASSERT(isHostFunction());
+    ASSERT(isHostFunctionNonInline());
     return static_cast<NativeExecutable*>(m_executable.get())->function();
 }
 
 inline NativeFunction JSFunction::nativeConstructor()
 {
-    ASSERT(isHostFunction());
+    ASSERT(isHostFunctionNonInline());
     return static_cast<NativeExecutable*>(m_executable.get())->constructor();
 }
 
+inline bool isHostFunction(JSValue value, NativeFunction nativeFunction)
+{
+    JSFunction* function = jsCast<JSFunction*>(getJSFunction(value));
+    if (!function || !function->isHostFunction())
+        return false;
+    return function->nativeFunction() == nativeFunction;
+}
+
 } // namespace JSC
 
 #endif // JSFunctionInlines_h
index bf83b8a..f901597 100644 (file)
@@ -353,7 +353,8 @@ void JSGlobalObject::reset(JSValue prototype)
 
     // Constructors
 
-    JSCell* objectConstructor = ObjectConstructor::create(vm, ObjectConstructor::createStructure(vm, this, m_functionPrototype.get()), m_objectPrototype.get());
+    ObjectConstructor* objectConstructor = ObjectConstructor::create(vm, ObjectConstructor::createStructure(vm, this, m_functionPrototype.get()), m_objectPrototype.get());
+    m_objectConstructor.set(vm, this, objectConstructor);
     JSCell* functionConstructor = FunctionConstructor::create(vm, FunctionConstructor::createStructure(vm, this, m_functionPrototype.get()), m_functionPrototype.get());
     JSCell* arrayConstructor = ArrayConstructor::create(vm, ArrayConstructor::createStructure(vm, this, m_functionPrototype.get()), m_arrayPrototype.get());
 
@@ -439,7 +440,10 @@ void JSGlobalObject::reset(JSValue prototype)
     GlobalPropertyInfo staticGlobals[] = {
         GlobalPropertyInfo(vm.propertyNames->NaN, jsNaN(), DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(vm.propertyNames->Infinity, jsNumber(std::numeric_limits<double>::infinity()), DontEnum | DontDelete | ReadOnly),
-        GlobalPropertyInfo(vm.propertyNames->undefinedKeyword, jsUndefined(), DontEnum | DontDelete | ReadOnly)
+        GlobalPropertyInfo(vm.propertyNames->undefinedKeyword, jsUndefined(), DontEnum | DontDelete | ReadOnly),
+        GlobalPropertyInfo(vm.propertyNames->undefinedPrivateName, jsUndefined(), DontEnum | DontDelete | ReadOnly),
+        GlobalPropertyInfo(vm.propertyNames->ObjectPrivateName, objectConstructor, DontEnum | DontDelete | ReadOnly),
+        GlobalPropertyInfo(vm.propertyNames->TypeErrorPrivateName, m_typeErrorConstructor.get(), DontEnum | DontDelete | ReadOnly)
     };
     addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
     
@@ -615,6 +619,7 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(&thisObject->m_syntaxErrorConstructor);
     visitor.append(&thisObject->m_typeErrorConstructor);
     visitor.append(&thisObject->m_URIErrorConstructor);
+    visitor.append(&thisObject->m_objectConstructor);
     visitor.append(&thisObject->m_promiseConstructor);
 
     visitor.append(&thisObject->m_evalFunction);
index f987e4a..6e94929 100644 (file)
@@ -68,6 +68,7 @@ class JSStack;
 class LLIntOffsetsExtractor;
 class Microtask;
 class NativeErrorConstructor;
+class ObjectConstructor;
 class ProgramCodeBlock;
 class ProgramExecutable;
 class RegExpConstructor;
@@ -159,6 +160,7 @@ protected:
     WriteBarrier<NativeErrorConstructor> m_typeErrorConstructor;
     WriteBarrier<NativeErrorConstructor> m_URIErrorConstructor;
     WriteBarrier<JSPromiseConstructor> m_promiseConstructor;
+    WriteBarrier<ObjectConstructor> m_objectConstructor;
 
     WriteBarrier<JSFunction> m_evalFunction;
     WriteBarrier<JSFunction> m_callFunction;
@@ -335,6 +337,7 @@ public:
     RegExpConstructor* regExpConstructor() const { return m_regExpConstructor.get(); }
 
     ErrorConstructor* errorConstructor() const { return m_errorConstructor.get(); }
+    ObjectConstructor* objectConstructor() const { return m_objectConstructor.get(); }
     NativeErrorConstructor* evalErrorConstructor() const { return m_evalErrorConstructor.get(); }
     NativeErrorConstructor* rangeErrorConstructor() const { return m_rangeErrorConstructor.get(); }
     NativeErrorConstructor* referenceErrorConstructor() const { return m_referenceErrorConstructor.get(); }
@@ -591,7 +594,7 @@ inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, PropertyName
 
 inline bool JSGlobalObject::symbolTableHasProperty(PropertyName propertyName)
 {
-    SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.publicName());
+    SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.uid());
     return !entry.isNull();
 }
 
index ff2c5cf..97cd3de 100644 (file)
@@ -87,7 +87,7 @@ static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* class
         int hashSizeMask = table->compactSize - 1;
         const HashEntry* entry = table->table;
         for (int i = 0; i <= hashSizeMask; ++i, ++entry) {
-            if (entry->key() && (!(entry->attributes() & DontEnum) || (mode == IncludeDontEnumProperties)) && !((entry->attributes() & Function) && didReify))
+            if (entry->key() && (!(entry->attributes() & DontEnum) || (mode == IncludeDontEnumProperties)) && !((entry->attributes() & BuiltinOrFunction) && didReify))
                 propertyNames.add(entry->key());
         }
     }
@@ -1618,7 +1618,7 @@ void JSObject::reifyStaticFunctionsForDelete(ExecState* exec)
             continue;
         PropertySlot slot(this);
         for (HashTable::ConstIterator iter = hashTable->begin(vm); iter != hashTable->end(vm); ++iter) {
-            if (iter->attributes() & Function)
+            if (iter->attributes() & BuiltinOrFunction)
                 setUpStaticFunctionSlot(globalObject()->globalExec(), *iter, this, Identifier(&vm, iter->key()), slot);
         }
     }
@@ -2236,6 +2236,16 @@ void JSObject::putDirectNativeFunction(VM& vm, JSGlobalObject* globalObject, con
     putDirect(vm, propertyName, function, attributes);
 }
 
+void JSObject::putDirectBuiltinFunction(VM& vm, JSGlobalObject* globalObject, const PropertyName& propertyName, FunctionExecutable* functionExecutable, unsigned attributes)
+{
+    StringImpl* name = propertyName.publicName();
+    if (!name)
+        name = vm.propertyNames->anonymous.impl();
+    ASSERT(name);
+    JSFunction* function = JSFunction::createBuiltinFunction(vm, static_cast<FunctionExecutable*>(functionExecutable), globalObject);
+    putDirect(vm, propertyName, function, attributes);
+}
+
 void JSObject::putDirectNativeFunctionWithoutTransition(VM& vm, JSGlobalObject* globalObject, const PropertyName& propertyName, unsigned functionLength, NativeFunction nativeFunction, Intrinsic intrinsic, unsigned attributes)
 {
     StringImpl* name = propertyName.publicName();
index 311171c..c872f62 100644 (file)
@@ -581,6 +581,7 @@ public:
     void putDirectUndefined(PropertyOffset offset) { locationForOffset(offset)->setUndefined(); }
 
     void putDirectNativeFunction(VM&, JSGlobalObject*, const PropertyName&, unsigned functionLength, NativeFunction, Intrinsic, unsigned attributes);
+    void putDirectBuiltinFunction(VM&, JSGlobalObject*, const PropertyName&, FunctionExecutable*, unsigned attributes);
     void putDirectNativeFunctionWithoutTransition(VM&, JSGlobalObject*, const PropertyName&, unsigned functionLength, NativeFunction, Intrinsic, unsigned attributes);
 
     JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
index b727e54..7efc76a 100644 (file)
@@ -64,6 +64,8 @@ void JSSymbolTableObject::getOwnNonIndexPropertyNames(JSObject* object, ExecStat
         ConcurrentJITLocker locker(thisObject->symbolTable()->m_lock);
         SymbolTable::Map::iterator end = thisObject->symbolTable()->end(locker);
         for (SymbolTable::Map::iterator it = thisObject->symbolTable()->begin(locker); it != end; ++it) {
+            if (it->key->isEmptyUnique())
+                continue;
             if (!(it->value.getAttributes() & DontEnum) || (mode == IncludeDontEnumProperties))
                 propertyNames.add(Identifier(exec, it->key.get()));
         }
index b5b20a8..d03b245 100644 (file)
@@ -72,7 +72,7 @@ inline bool symbolTableGet(
 {
     SymbolTable& symbolTable = *object->symbolTable();
     ConcurrentJITLocker locker(symbolTable.m_lock);
-    SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.publicName());
+    SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
     if (iter == symbolTable.end(locker))
         return false;
     SymbolTableEntry::Fast entry = iter->value;
@@ -87,7 +87,7 @@ inline bool symbolTableGet(
 {
     SymbolTable& symbolTable = *object->symbolTable();
     ConcurrentJITLocker locker(symbolTable.m_lock);
-    SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.publicName());
+    SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
     if (iter == symbolTable.end(locker))
         return false;
     SymbolTableEntry::Fast entry = iter->value;
@@ -104,7 +104,7 @@ inline bool symbolTableGet(
 {
     SymbolTable& symbolTable = *object->symbolTable();
     ConcurrentJITLocker locker(symbolTable.m_lock);
-    SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.publicName());
+    SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
     if (iter == symbolTable.end(locker))
         return false;
     SymbolTableEntry::Fast entry = iter->value;
@@ -126,7 +126,7 @@ inline bool symbolTablePut(
     {
         SymbolTable& symbolTable = *object->symbolTable();
         GCSafeConcurrentJITLocker locker(symbolTable.m_lock, exec->vm().heap);
-        SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.publicName());
+        SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
         if (iter == symbolTable.end(locker))
             return false;
         bool wasFat;
@@ -159,7 +159,7 @@ inline bool symbolTablePutWithAttributes(
     {
         SymbolTable& symbolTable = *object->symbolTable();
         ConcurrentJITLocker locker(symbolTable.m_lock);
-        SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.publicName());
+        SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
         if (iter == symbolTable.end(locker))
             return false;
         SymbolTableEntry& entry = iter->value;
index f6ddcb5..197d847 100644 (file)
@@ -68,7 +68,7 @@ void HashTable::deleteTable() const
 bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, PropertyName propertyName, PropertySlot& slot)
 {
     ASSERT(thisObj->globalObject());
-    ASSERT(entry->attributes() & Function);
+    ASSERT(entry->attributes() & BuiltinOrFunction);
     VM& vm = exec->vm();
     unsigned attributes;
     PropertyOffset offset = thisObj->getDirectOffset(vm, propertyName, attributes);
@@ -79,9 +79,13 @@ bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject*
         if (thisObj->staticFunctionsReified())
             return false;
     
-        thisObj->putDirectNativeFunction(
-            vm, thisObj->globalObject(), propertyName, entry->functionLength(),
-            entry->function(), entry->intrinsic(), entry->attributes());
+        if (entry->attributes() & Builtin)
+            thisObj->putDirectBuiltinFunction(vm, thisObj->globalObject(), propertyName, entry->builtinGenerator()(vm), entry->attributes());
+        else {
+            thisObj->putDirectNativeFunction(
+                vm, thisObj->globalObject(), propertyName, entry->functionLength(),
+                entry->function(), entry->intrinsic(), entry->attributes());
+        }
         offset = thisObj->getDirectOffset(vm, propertyName, attributes);
         ASSERT(isValidOffset(offset));
     }
index bde83d4..dba389e 100644 (file)
@@ -43,6 +43,7 @@ namespace JSC {
     // ie. typedef JSValue (*GetFunction)(ExecState*, JSObject* baseObject)
     typedef PropertySlot::GetValueFunc GetFunction;
     typedef PutPropertySlot::PutValueFunc PutFunction;
+    typedef FunctionExecutable* (*BuiltinGenerator)(VM&);
 
     class HashEntry {
         WTF_MAKE_FAST_ALLOCATED;
@@ -68,11 +69,12 @@ namespace JSC {
             return m_intrinsic;
         }
 
+        BuiltinGenerator builtinGenerator() const { ASSERT(m_attributes & Builtin); return m_u.builtinGenerator.generatorValue; }
         NativeFunction function() const { ASSERT(m_attributes & Function); return m_u.function.functionValue; }
         unsigned char functionLength() const { ASSERT(m_attributes & Function); return static_cast<unsigned char>(m_u.function.length); }
 
-        GetFunction propertyGetter() const { ASSERT(!(m_attributes & Function)); return m_u.property.get; }
-        PutFunction propertyPutter() const { ASSERT(!(m_attributes & Function)); return m_u.property.put; }
+        GetFunction propertyGetter() const { ASSERT(!(m_attributes & BuiltinOrFunction)); return m_u.property.get; }
+        PutFunction propertyPutter() const { ASSERT(!(m_attributes & BuiltinOrFunction)); return m_u.property.put; }
 
         intptr_t lexerValue() const { ASSERT(!m_attributes); return m_u.lexer.value; }
 
@@ -94,6 +96,10 @@ namespace JSC {
                 intptr_t length; // number of arguments for function
             } function;
             struct {
+                BuiltinGenerator generatorValue;
+                intptr_t unused;
+            } builtinGenerator;
+            struct {
                 GetFunction get;
                 PutFunction put;
             } property;
@@ -209,7 +215,7 @@ namespace JSC {
     private:
         ALWAYS_INLINE const HashEntry* entry(PropertyName propertyName) const
         {
-            StringImpl* impl = propertyName.publicName();
+            StringImpl* impl = propertyName.uid();
             if (!impl)
                 return 0;
         
@@ -249,7 +255,7 @@ namespace JSC {
         if (!entry) // not found, forward to parent
             return ParentImp::getOwnPropertySlot(thisObj, exec, propertyName, slot);
 
-        if (entry->attributes() & Function)
+        if (entry->attributes() & BuiltinOrFunction)
             return setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
 
         slot.setCacheableCustom(thisObj, entry->attributes(), entry->propertyGetter());
@@ -286,7 +292,7 @@ namespace JSC {
         if (!entry) // not found, forward to parent
             return ParentImp::getOwnPropertySlot(thisObj, exec, propertyName, slot);
 
-        ASSERT(!(entry->attributes() & Function));
+        ASSERT(!(entry->attributes() & BuiltinOrFunction));
 
         slot.setCacheableCustom(thisObj, entry->attributes(), entry->propertyGetter());
         return true;
@@ -295,7 +301,7 @@ namespace JSC {
     inline void putEntry(ExecState* exec, const HashEntry* entry, JSObject* base, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
     {
         // If this is a function put it as an override property.
-        if (entry->attributes() & Function) {
+        if (entry->attributes() & BuiltinOrFunction) {
             if (JSObject* thisObject = jsDynamicCast<JSObject*>(slot.thisValue()))
                 thisObject->putDirect(exec->vm(), propertyName, value);
         } else if (!(entry->attributes() & ReadOnly)) {
index 8dc4a02..6260055 100644 (file)
@@ -38,6 +38,20 @@ NativeErrorConstructor::NativeErrorConstructor(VM& vm, Structure* structure)
 {
 }
 
+void NativeErrorConstructor::finishCreation(VM& vm, JSGlobalObject* globalObject, Structure* prototypeStructure, const String& name)
+{
+    Base::finishCreation(vm, name);
+    ASSERT(inherits(info()));
+    
+    NativeErrorPrototype* prototype = NativeErrorPrototype::create(vm, globalObject, prototypeStructure, name, this);
+    
+    putDirect(vm, vm.propertyNames->length, jsNumber(1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5
+    putDirect(vm, vm.propertyNames->prototype, prototype, DontDelete | ReadOnly | DontEnum);
+    m_errorStructure.set(vm, this, ErrorInstance::createStructure(vm, globalObject, prototype));
+    ASSERT(m_errorStructure);
+    ASSERT(m_errorStructure->isObject());
+}
+
 void NativeErrorConstructor::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
     NativeErrorConstructor* thisObject = jsCast<NativeErrorConstructor*>(cell);
index 740d3f9..438a3af 100644 (file)
@@ -51,19 +51,7 @@ namespace JSC {
         Structure* errorStructure() { return m_errorStructure.get(); }
 
     protected:
-        void finishCreation(VM& vm, JSGlobalObject* globalObject, Structure* prototypeStructure, const String& name)
-        {
-            Base::finishCreation(vm, name);
-            ASSERT(inherits(info()));
-
-            NativeErrorPrototype* prototype = NativeErrorPrototype::create(vm, globalObject, prototypeStructure, name, this);
-
-            putDirect(vm, vm.propertyNames->length, jsNumber(1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5
-            putDirect(vm, vm.propertyNames->prototype, prototype, DontDelete | ReadOnly | DontEnum);
-            m_errorStructure.set(vm, this, ErrorInstance::createStructure(vm, globalObject, prototype));
-            ASSERT(m_errorStructure);
-            ASSERT(m_errorStructure->isObject());
-        }
+        void finishCreation(VM&, JSGlobalObject*, Structure* prototypeStructure, const String& name);
 
     private:
         NativeErrorConstructor(VM&, Structure*);
index 338ed42..a954cc0 100644 (file)
@@ -36,13 +36,15 @@ class JSObject;
 // ECMA 262-3 8.6.1
 // Property attributes
 enum Attribute {
-    None         = 0,
-    ReadOnly     = 1 << 1,  // property can be only read, not written
-    DontEnum     = 1 << 2,  // property doesn't appear in (for .. in ..)
-    DontDelete   = 1 << 3,  // property can't be deleted
-    Function     = 1 << 4,  // property is a function - only used by static hashtables
-    Accessor     = 1 << 5,  // property is a getter/setter
-    CustomAccessor = 1 << 6,
+    None              = 0,
+    ReadOnly          = 1 << 1,  // property can be only read, not written
+    DontEnum          = 1 << 2,  // property doesn't appear in (for .. in ..)
+    DontDelete        = 1 << 3,  // property can't be deleted
+    Function          = 1 << 4,  // property is a function - only used by static hashtables
+    Accessor          = 1 << 5,  // property is a getter/setter
+    CustomAccessor    = 1 << 6,
+    Builtin           = 1 << 7, // property is a builtin function - only used by static hashtables
+    BuiltinOrFunction = Builtin | Function, // helper only used by static hashtables
 };
 
 class PropertySlot {
index 74bbd20..8c1205c 100644 (file)
@@ -32,6 +32,7 @@
 #include "ArgList.h"
 #include "ArityCheckFailReturnThunks.h"
 #include "ArrayBufferNeuteringWatchpoint.h"
+#include "BuiltinExecutables.h"
 #include "CodeBlock.h"
 #include "CodeCache.h"
 #include "CommonIdentifiers.h"
 #include "Lookup.h"
 #include "MapData.h"
 #include "Nodes.h"
+#include "Parser.h"
 #include "ParserArena.h"
+#include "PropertyMapHashTable.h"
 #include "RegExpCache.h"
 #include "RegExpObject.h"
 #include "SimpleTypedArrayController.h"
 #include "SourceProviderCache.h"
 #include "StrictEvalActivation.h"
 #include "StrongInlines.h"
+#include "StructureInlines.h"
 #include "UnlinkedCodeBlock.h"
 #include "WeakMapData.h"
 #include <wtf/ProcessID.h>
@@ -226,6 +230,7 @@ VM::VM(VMType vmType, HeapType heapType)
     , m_inDefineOwnProperty(false)
     , m_codeCache(CodeCache::create())
     , m_enabledProfiler(nullptr)
+    , m_builtinExecutables(BuiltinExecutables::create(*this))
 {
     interpreter = new Interpreter(*this);
     StackBounds stack = wtfThreadData().stack();
index 5a84105..6958ac3 100644 (file)
@@ -44,6 +44,7 @@
 #include "PrivateName.h"
 #include "PrototypeMap.h"
 #include "SmallStrings.h"
+#include "SourceCode.h"
 #include "Strong.h"
 #include "ThunkGenerators.h"
 #include "TypedArrayController.h"
@@ -69,6 +70,7 @@
 namespace JSC {
 
     class ArityCheckFailReturnThunks;
+    class BuiltinExecutables;
     class CodeBlock;
     class CodeCache;
     class CommonIdentifiers;
@@ -497,6 +499,8 @@ namespace JSC {
         void registerWatchpointForImpureProperty(const Identifier&, Watchpoint*);
         // FIXME: Use AtomicString once it got merged with Identifier.
         JS_EXPORT_PRIVATE void addImpureProperty(const String&);
+        
+        BuiltinExecutables* builtinExecutables() { return m_builtinExecutables.get(); }
 
     private:
         friend class LLIntOffsetsExtractor;
@@ -537,10 +541,9 @@ namespace JSC {
         JSValue m_exception;
         bool m_inDefineOwnProperty;
         OwnPtr<CodeCache> m_codeCache;
-        RefCountedArray<StackFrame> m_exceptionStack;
-
         LegacyProfiler* m_enabledProfiler;
-
+        OwnPtr<BuiltinExecutables> m_builtinExecutables;
+        RefCountedArray<StackFrame> m_exceptionStack;
         HashMap<String, RefPtr<WatchpointSet>> m_impurePropertyWatchpointSets;
     };
 
index 56bf447..7f521a8 100644 (file)
@@ -6,6 +6,7 @@
 include_directories(${THIRDPARTY_DIR}/gtest
     ${THIRDPARTY_DIR}/gtest/include
     ${JAVASCRIPTCORE_DIR}
+    ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}
     ${WTF_DIR}
 )
 
index b027343..25aed52 100644 (file)
@@ -1,3 +1,16 @@
+2014-02-11  Oliver Hunt  <oliver@apple.com>
+
+        Make it possible to implement JS builtins in JS
+        https://bugs.webkit.org/show_bug.cgi?id=127887
+
+        Reviewed by Michael Saboff.
+
+        CMake updates
+
+        * DumpRenderTree/CMakeLists.txt:
+        * WebKitTestRunner/CMakeLists.txt:
+        * WinCELauncher/CMakeLists.txt:
+
 2014-02-11  Filip Pizlo  <fpizlo@apple.com>
 
         It should be possible to force copy-webkitlibraries-blahblah to copy things regardless of timestamp
index 7b8aa18..549cd40 100644 (file)
@@ -58,6 +58,7 @@ set(DumpRenderTree_INCLUDE_DIRECTORIES
     ${JAVASCRIPTCORE_DIR}/profiler
     ${JAVASCRIPTCORE_DIR}/runtime
     ${JAVASCRIPTCORE_DIR}/ForwardingHeaders
+    ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}
     ${TOOLS_DIR}/DumpRenderTree
     ${WTF_DIR}
     ${CMAKE_SOURCE_DIR}/Source
index 5a346d7..cb4b191 100644 (file)
@@ -28,6 +28,7 @@ set(WebKitTestRunner_INCLUDE_DIRECTORIES
     ${WEBKIT_TESTRUNNER_DIR}/InjectedBundle/atk
     ${JAVASCRIPTCORE_DIR}
     ${JAVASCRIPTCORE_DIR}/ForwardingHeaders
+    ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}
     ${WEBCORE_DIR}/editing
     ${WEBCORE_DIR}/platform
     ${WEBCORE_DIR}/platform/graphics
index 914bb2b..b19fc61 100644 (file)
@@ -6,6 +6,7 @@ set(WinCELauncher_INCLUDE_DIRECTORIES
     "${WEBCORE_DIR}/platform/network"
     "${WEBCORE_DIR}/platform/text"
     "${JAVASCRIPTCORE_DIR}"
+    "${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}"
     "${WTF_DIR}"
     "${DERIVED_SOURCES_DIR}"
     "${CMAKE_BINARY_DIR}"