Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (164834 => 164835)
--- trunk/Source/_javascript_Core/ChangeLog 2014-02-27 23:24:05 UTC (rev 164834)
+++ trunk/Source/_javascript_Core/ChangeLog 2014-02-27 23:25:29 UTC (rev 164835)
@@ -1,3 +1,43 @@
+2014-02-27 Oliver Hunt <[email protected]>
+
+ Slow cases for function.apply and function.call should not require vm re-entry
+ https://bugs.webkit.org/show_bug.cgi?id=129454
+
+ Reviewed by Geoffrey Garen.
+
+ Implement call and apply using builtins. Happily the use
+ of @call and @apply don't perform function equality checks
+ and just plant direct var_args calls. This did expose a few
+ codegen issues, but they're all covered by existing tests
+ once call and apply are implemented in JS.
+
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * builtins/Function.prototype.js: Added.
+ (call):
+ (apply):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::CallFunctionCallDotNode::emitBytecode):
+ (JSC::ApplyFunctionCallDotNode::emitBytecode):
+ * dfg/DFGCapabilities.cpp:
+ (JSC::DFG::capabilityLevel):
+ * interpreter/Interpreter.cpp:
+ (JSC::sizeFrameForVarargs):
+ (JSC::loadVarargs):
+ * interpreter/Interpreter.h:
+ * jit/JITCall.cpp:
+ (JSC::JIT::compileLoadVarargs):
+ * parser/ASTBuilder.h:
+ (JSC::ASTBuilder::makeFunctionCallNode):
+ * parser/Lexer.cpp:
+ (JSC::isSafeBuiltinIdentifier):
+ * runtime/CommonIdentifiers.h:
+ * runtime/FunctionPrototype.cpp:
+ (JSC::FunctionPrototype::addFunctionProperties):
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::putDirectBuiltinFunction):
+ (JSC::JSObject::putDirectBuiltinFunctionWithoutTransition):
+ * runtime/JSObject.h:
+
2014-02-27 Joseph Pecoraro <[email protected]>
Web Inspector: Better name for RemoteInspectorDebuggableConnection dispatch queue
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (164834 => 164835)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2014-02-27 23:24:05 UTC (rev 164834)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2014-02-27 23:25:29 UTC (rev 164835)
@@ -2729,6 +2729,7 @@
A7A8AF3117ADB5F3005AB174 /* Uint8ClampedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Uint8ClampedArray.h; sourceTree = "<group>"; };
A7A8AF3217ADB5F3005AB174 /* Uint16Array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Uint16Array.h; sourceTree = "<group>"; };
A7A8AF3317ADB5F3005AB174 /* Uint32Array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Uint32Array.h; sourceTree = "<group>"; };
+ A7A979C418BE8D9E002C3733 /* Function.prototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = Function.prototype.js; sourceTree = "<group>"; };
A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutableAllocator.h; sourceTree = "<group>"; };
A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocator.cpp; sourceTree = "<group>"; };
A7B4ACAE1484C9CE00B38A36 /* JSExportMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSExportMacros.h; sourceTree = "<group>"; };
@@ -4833,6 +4834,7 @@
A7D801A21880D66E0026C39B /* BuiltinExecutables.h */,
A75EE9B018AAB7E200AAD043 /* BuiltinNames.h */,
7CFBAC1C18B535E500D00750 /* Promise.prototype.js */,
+ A7A979C418BE8D9E002C3733 /* Function.prototype.js */,
);
path = builtins;
sourceTree = "<group>";
Added: trunk/Source/_javascript_Core/builtins/Function.prototype.js (0 => 164835)
--- trunk/Source/_javascript_Core/builtins/Function.prototype.js (rev 0)
+++ trunk/Source/_javascript_Core/builtins/Function.prototype.js 2014-02-27 23:25:29 UTC (rev 164835)
@@ -0,0 +1,34 @@
+/*
+ * 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 call(thisArgument) {
+ "use strict";
+ return this.@call(...arguments);
+}
+
+function apply(thisValue, argumentValues) {
+ "use strict";
+ return this.@apply(thisValue, argumentValues);
+}
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (164834 => 164835)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2014-02-27 23:24:05 UTC (rev 164834)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2014-02-27 23:25:29 UTC (rev 164835)
@@ -28,6 +28,7 @@
#include "Nodes.h"
#include "NodeConstructors.h"
+#include "BuiltinNames.h"
#include "BytecodeGenerator.h"
#include "CallFrame.h"
#include "Debugger.h"
@@ -549,7 +550,7 @@
RefPtr<RegisterID> function;
bool emitCallCheck = !generator.isBuiltinFunction();
if (emitCallCheck) {
- function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().call);
+ function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().callPublicName());
generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
}
RefPtr<RegisterID> returnValue = generator.finalDestination(dst);
@@ -620,7 +621,7 @@
RefPtr<RegisterID> returnValue = generator.finalDestination(dst, function.get());
bool emitCallCheck = !generator.isBuiltinFunction();
if (emitCallCheck) {
- function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().apply);
+ function = generator.emitGetById(generator.tempDestination(dst), base.get(), generator.propertyNames().builtinNames().applyPublicName());
generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
}
if (mayBeCall) {
Modified: trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp (164834 => 164835)
--- trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2014-02-27 23:24:05 UTC (rev 164834)
+++ trunk/Source/_javascript_Core/dfg/DFGCapabilities.cpp 2014-02-27 23:25:29 UTC (rev 164835)
@@ -211,7 +211,8 @@
}
case op_call_varargs:
- if (codeBlock->usesArguments() && pc[4].u.operand == codeBlock->argumentsRegister().offset())
+ if (codeBlock->usesArguments() && pc[4].u.operand == codeBlock->argumentsRegister().offset()
+ && !pc[6].u.operand)
return CanInline;
// FIXME: We should handle this.
// https://bugs.webkit.org/show_bug.cgi?id=127626
Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (164834 => 164835)
--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2014-02-27 23:24:05 UTC (rev 164834)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2014-02-27 23:25:29 UTC (rev 164835)
@@ -137,10 +137,14 @@
return interpreter->execute(eval, callFrame, thisValue, callerScopeChain);
}
-CallFrame* sizeFrameForVarargs(CallFrame* callFrame, JSStack* stack, JSValue arguments, int firstFreeRegister, int32_t firstVarArgOffset)
+CallFrame* sizeFrameForVarargs(CallFrame* callFrame, JSStack* stack, JSValue arguments, int firstFreeRegister, uint32_t firstVarArgOffset)
{
if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
- unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis() - firstVarArgOffset;
+ unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
+ if (argumentCountIncludingThis > firstVarArgOffset)
+ argumentCountIncludingThis -= firstVarArgOffset;
+ else
+ argumentCountIncludingThis = 1;
unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + argumentCountIncludingThis + JSStack::CallFrameHeaderSize + 1);
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
if (argumentCountIncludingThis > Arguments::MaxArguments + 1 || !stack->ensureCapacityFor(newCallFrame->registers())) {
@@ -168,7 +172,11 @@
if (asObject(arguments)->classInfo() == Arguments::info()) {
Arguments* argsObject = asArguments(arguments);
- unsigned argCount = argsObject->length(callFrame) - firstVarArgOffset;
+ unsigned argCount = argsObject->length(callFrame);
+ if (argCount >= firstVarArgOffset)
+ argCount -= firstVarArgOffset;
+ else
+ argCount = 0;
unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + CallFrame::offsetFor(argCount + 1));
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
@@ -180,7 +188,11 @@
if (isJSArray(arguments)) {
JSArray* array = asArray(arguments);
- unsigned argCount = array->length() - firstVarArgOffset;
+ unsigned argCount = array->length();
+ if (argCount >= firstVarArgOffset)
+ argCount -= firstVarArgOffset;
+ else
+ argCount = 0;
unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + CallFrame::offsetFor(argCount + 1));
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
@@ -191,7 +203,11 @@
}
JSObject* argObject = asObject(arguments);
- unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame) - firstVarArgOffset;
+ unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
+ if (argCount >= firstVarArgOffset)
+ argCount -= firstVarArgOffset;
+ else
+ argCount = 0;
unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -firstFreeRegister + CallFrame::offsetFor(argCount + 1));
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
@@ -201,11 +217,14 @@
return newCallFrame;
}
-void loadVarargs(CallFrame* callFrame, CallFrame* newCallFrame, JSValue thisValue, JSValue arguments, int32_t firstVarArgOffset)
+void loadVarargs(CallFrame* callFrame, CallFrame* newCallFrame, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset)
{
if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
- unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis() - firstVarArgOffset;
-
+ unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
+ if (argumentCountIncludingThis > firstVarArgOffset)
+ argumentCountIncludingThis -= firstVarArgOffset;
+ else
+ argumentCountIncludingThis = 1;
newCallFrame->setArgumentCountIncludingThis(argumentCountIncludingThis);
newCallFrame->setThisValue(thisValue);
for (size_t i = firstVarArgOffset; i < callFrame->argumentCount(); ++i)
@@ -221,25 +240,38 @@
if (asObject(arguments)->classInfo() == Arguments::info()) {
Arguments* argsObject = asArguments(arguments);
- unsigned argCount = argsObject->length(callFrame) - firstVarArgOffset;
- newCallFrame->setArgumentCountIncludingThis(argCount + 1);
+ unsigned argCount = argsObject->length(callFrame);
+ if (argCount >= firstVarArgOffset) {
+ argCount -= firstVarArgOffset;
+ newCallFrame->setArgumentCountIncludingThis(argCount + 1);
+ argsObject->copyToArguments(callFrame, newCallFrame, argCount, firstVarArgOffset);
+ } else
+ newCallFrame->setArgumentCountIncludingThis(1);
newCallFrame->setThisValue(thisValue);
- argsObject->copyToArguments(callFrame, newCallFrame, argCount, firstVarArgOffset);
return;
}
if (isJSArray(arguments)) {
JSArray* array = asArray(arguments);
- unsigned argCount = array->length() - firstVarArgOffset;
- newCallFrame->setArgumentCountIncludingThis(argCount + 1);
+ unsigned argCount = array->length();
+ if (argCount >= firstVarArgOffset) {
+ argCount -= firstVarArgOffset;
+ newCallFrame->setArgumentCountIncludingThis(argCount + 1);
+ array->copyToArguments(callFrame, newCallFrame, argCount, firstVarArgOffset);
+ } else
+ newCallFrame->setArgumentCountIncludingThis(1);
newCallFrame->setThisValue(thisValue);
- array->copyToArguments(callFrame, newCallFrame, argCount, firstVarArgOffset);
return;
}
JSObject* argObject = asObject(arguments);
- unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame) - firstVarArgOffset;
- newCallFrame->setArgumentCountIncludingThis(argCount + 1);
+ unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
+ if (argCount >= firstVarArgOffset) {
+ argCount -= firstVarArgOffset;
+ newCallFrame->setArgumentCountIncludingThis(argCount + 1);
+ } else
+ newCallFrame->setArgumentCountIncludingThis(1);
+
newCallFrame->setThisValue(thisValue);
for (size_t i = 0; i < argCount; ++i) {
newCallFrame->setArgument(i, asObject(arguments)->get(callFrame, i + firstVarArgOffset));
Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.h (164834 => 164835)
--- trunk/Source/_javascript_Core/interpreter/Interpreter.h 2014-02-27 23:24:05 UTC (rev 164834)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.h 2014-02-27 23:25:29 UTC (rev 164835)
@@ -285,8 +285,8 @@
};
JSValue eval(CallFrame*);
- CallFrame* sizeFrameForVarargs(CallFrame*, JSStack*, JSValue, int, int32_t firstVarArgOffset);
- void loadVarargs(CallFrame*, CallFrame*, JSValue, JSValue, int32_t firstVarArgOffset);
+ CallFrame* sizeFrameForVarargs(CallFrame*, JSStack*, JSValue, int, uint32_t firstVarArgOffset);
+ void loadVarargs(CallFrame*, CallFrame*, JSValue, JSValue, uint32_t firstVarArgOffset);
} // namespace JSC
#endif // Interpreter_h
Modified: trunk/Source/_javascript_Core/jit/JITCall.cpp (164834 => 164835)
--- trunk/Source/_javascript_Core/jit/JITCall.cpp 2014-02-27 23:24:05 UTC (rev 164834)
+++ trunk/Source/_javascript_Core/jit/JITCall.cpp 2014-02-27 23:25:29 UTC (rev 164835)
@@ -71,8 +71,14 @@
slowCase.append(branch64(NotEqual, regT0, TrustedImm64(JSValue::encode(JSValue()))));
emitGetFromCallFrameHeader32(JSStack::ArgumentCount, regT0);
- if (firstVarArgOffset)
+ if (firstVarArgOffset) {
+ Jump sufficientArguments = branch32(GreaterThan, regT0, TrustedImm32(firstVarArgOffset + 1));
+ move(TrustedImm32(1), regT0);
+ Jump endVarArgs = jump();
+ sufficientArguments.link(this);
sub32(TrustedImm32(firstVarArgOffset), regT0);
+ endVarArgs.link(this);
+ }
slowCase.append(branch32(Above, regT0, TrustedImm32(Arguments::MaxArguments + 1)));
// regT0: argumentCountIncludingThis
move(regT0, regT1);
Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (164834 => 164835)
--- trunk/Source/_javascript_Core/parser/ASTBuilder.h 2014-02-27 23:24:05 UTC (rev 164834)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h 2014-02-27 23:25:29 UTC (rev 164835)
@@ -26,6 +26,7 @@
#ifndef ASTBuilder_h
#define ASTBuilder_h
+#include "BuiltinNames.h"
#include "NodeConstructors.h"
#include "SyntaxChecker.h"
#include <utility>
@@ -888,9 +889,9 @@
ASSERT(func->isDotAccessorNode());
DotAccessorNode* dot = static_cast<DotAccessorNode*>(func);
FunctionCallDotNode* node;
- if (dot->identifier() == m_vm->propertyNames->call || dot->identifier() == m_vm->propertyNames->callPrivateName)
+ if (dot->identifier() == m_vm->propertyNames->builtinNames().callPublicName() || dot->identifier() == m_vm->propertyNames->builtinNames().callPrivateName())
node = new (m_vm) CallFunctionCallDotNode(location, dot->base(), dot->identifier(), args, divot, divotStart, divotEnd);
- else if (dot->identifier() == m_vm->propertyNames->apply || dot->identifier() == m_vm->propertyNames->applyPrivateName)
+ else if (dot->identifier() == m_vm->propertyNames->builtinNames().applyPublicName() || dot->identifier() == m_vm->propertyNames->builtinNames().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);
Modified: trunk/Source/_javascript_Core/parser/Lexer.cpp (164834 => 164835)
--- trunk/Source/_javascript_Core/parser/Lexer.cpp 2014-02-27 23:24:05 UTC (rev 164834)
+++ trunk/Source/_javascript_Core/parser/Lexer.cpp 2014-02-27 23:25:29 UTC (rev 164835)
@@ -27,6 +27,7 @@
#include "JSFunctionInlines.h"
+#include "BuiltinNames.h"
#include "JSGlobalObjectFunctions.h"
#include "Identifier.h"
#include "NodeInfo.h"
@@ -765,9 +766,9 @@
/* 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)
+ if (*ident == vm.propertyNames->builtinNames().callPublicName())
return false;
- if (*ident == vm.propertyNames->apply)
+ if (*ident == vm.propertyNames->builtinNames().applyPublicName())
return false;
if (*ident == vm.propertyNames->eval)
return false;
Modified: trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h (164834 => 164835)
--- trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h 2014-02-27 23:24:05 UTC (rev 164834)
+++ trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h 2014-02-27 23:25:29 UTC (rev 164835)
@@ -63,7 +63,6 @@
macro(__lookupSetter__) \
macro(add) \
macro(anonymous) \
- macro(apply) \
macro(arguments) \
macro(bind) \
macro(buffer) \
@@ -73,7 +72,6 @@
macro(bytecodeIndex) \
macro(bytecodes) \
macro(bytecodesID) \
- macro(call) \
macro(callee) \
macro(caller) \
macro(cast) \
@@ -207,8 +205,6 @@
macro(yield)
#define JSC_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \
- macro(apply) \
- macro(call) \
macro(iterator) \
macro(iteratorNext) \
macro(resolve) \
Modified: trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp (164834 => 164835)
--- trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp 2014-02-27 23:24:05 UTC (rev 164834)
+++ trunk/Source/_javascript_Core/runtime/FunctionPrototype.cpp 2014-02-27 23:25:29 UTC (rev 164835)
@@ -22,6 +22,8 @@
#include "FunctionPrototype.h"
#include "Arguments.h"
+#include "BuiltinExecutables.h"
+#include "BuiltinNames.h"
#include "JSArray.h"
#include "JSBoundFunction.h"
#include "JSFunction.h"
@@ -38,8 +40,6 @@
const ClassInfo FunctionPrototype::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionPrototype) };
static EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*);
-static EncodedJSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*);
-static EncodedJSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState*);
FunctionPrototype::FunctionPrototype(VM& vm, Structure* structure)
@@ -60,12 +60,9 @@
JSFunction* toStringFunction = JSFunction::create(vm, globalObject, 0, vm.propertyNames->toString.string(), functionProtoFuncToString);
putDirectWithoutTransition(vm, vm.propertyNames->toString, toStringFunction, DontEnum);
- *applyFunction = JSFunction::create(vm, globalObject, 2, vm.propertyNames->apply.string(), functionProtoFuncApply);
- putDirectWithoutTransition(vm, vm.propertyNames->apply, *applyFunction, DontEnum);
+ *applyFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().applyPublicName(), functionPrototypeApplyCodeGenerator(vm), DontEnum);
+ *callFunction = putDirectBuiltinFunctionWithoutTransition(vm, globalObject, vm.propertyNames->builtinNames().callPublicName(), functionPrototypeCallCodeGenerator(vm), DontEnum);
- *callFunction = JSFunction::create(vm, globalObject, 1, vm.propertyNames->call.string(), functionProtoFuncCall);
- putDirectWithoutTransition(vm, vm.propertyNames->call, *callFunction, DontEnum);
-
JSFunction* bindFunction = JSFunction::create(vm, globalObject, 1, vm.propertyNames->bind.string(), functionProtoFuncBind);
putDirectWithoutTransition(vm, vm.propertyNames->bind, bindFunction, DontEnum);
}
@@ -124,55 +121,6 @@
return throwVMTypeError(exec);
}
-EncodedJSValue JSC_HOST_CALL functionProtoFuncApply(ExecState* exec)
-{
- JSValue thisValue = exec->hostThisValue();
- CallData callData;
- CallType callType = getCallData(thisValue, callData);
- if (callType == CallTypeNone)
- return throwVMTypeError(exec);
-
- JSValue array = exec->argument(1);
-
- MarkedArgumentBuffer applyArgs;
- if (!array.isUndefinedOrNull()) {
- if (!array.isObject())
- return throwVMTypeError(exec);
- if (asObject(array)->classInfo() == Arguments::info()) {
- if (asArguments(array)->length(exec) > Arguments::MaxArguments)
- return JSValue::encode(throwStackOverflowError(exec));
- asArguments(array)->fillArgList(exec, applyArgs);
- } else if (isJSArray(array)) {
- if (asArray(array)->length() > Arguments::MaxArguments)
- return JSValue::encode(throwStackOverflowError(exec));
- asArray(array)->fillArgList(exec, applyArgs);
- } else {
- unsigned length = asObject(array)->get(exec, exec->propertyNames().length).toUInt32(exec);
- if (length > Arguments::MaxArguments)
- return JSValue::encode(throwStackOverflowError(exec));
-
- for (unsigned i = 0; i < length; ++i)
- applyArgs.append(asObject(array)->get(exec, i));
- }
- }
-
- return JSValue::encode(call(exec, thisValue, callType, callData, exec->argument(0), applyArgs));
-}
-
-EncodedJSValue JSC_HOST_CALL functionProtoFuncCall(ExecState* exec)
-{
- JSValue thisValue = exec->hostThisValue();
- CallData callData;
- CallType callType = getCallData(thisValue, callData);
- if (callType == CallTypeNone)
- return throwVMTypeError(exec);
-
- ArgList args(exec);
- ArgList callArgs;
- args.getSlice(1, callArgs);
- return JSValue::encode(call(exec, thisValue, callType, callData, exec->argument(0), callArgs));
-}
-
// 15.3.4.5 Function.prototype.bind (thisArg [, arg1 [, arg2, ...]])
EncodedJSValue JSC_HOST_CALL functionProtoFuncBind(ExecState* exec)
{
Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (164834 => 164835)
--- trunk/Source/_javascript_Core/runtime/JSObject.cpp 2014-02-27 23:24:05 UTC (rev 164834)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp 2014-02-27 23:25:29 UTC (rev 164835)
@@ -2245,7 +2245,7 @@
putDirect(vm, propertyName, function, attributes);
}
-void JSObject::putDirectBuiltinFunction(VM& vm, JSGlobalObject* globalObject, const PropertyName& propertyName, FunctionExecutable* functionExecutable, unsigned attributes)
+JSFunction* JSObject::putDirectBuiltinFunction(VM& vm, JSGlobalObject* globalObject, const PropertyName& propertyName, FunctionExecutable* functionExecutable, unsigned attributes)
{
StringImpl* name = propertyName.publicName();
if (!name)
@@ -2253,8 +2253,20 @@
ASSERT(name);
JSFunction* function = JSFunction::createBuiltinFunction(vm, static_cast<FunctionExecutable*>(functionExecutable), globalObject);
putDirect(vm, propertyName, function, attributes);
+ return function;
}
+JSFunction* JSObject::putDirectBuiltinFunctionWithoutTransition(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);
+ putDirectWithoutTransition(vm, propertyName, function, attributes);
+ return function;
+}
+
void JSObject::putDirectNativeFunctionWithoutTransition(VM& vm, JSGlobalObject* globalObject, const PropertyName& propertyName, unsigned functionLength, NativeFunction nativeFunction, Intrinsic intrinsic, unsigned attributes)
{
StringImpl* name = propertyName.publicName();
Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (164834 => 164835)
--- trunk/Source/_javascript_Core/runtime/JSObject.h 2014-02-27 23:24:05 UTC (rev 164834)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h 2014-02-27 23:25:29 UTC (rev 164835)
@@ -67,6 +67,7 @@
class GetterSetter;
class HashEntry;
class InternalFunction;
+class JSFunction;
class LLIntOffsetsExtractor;
class MarkedBlock;
class PropertyDescriptor;
@@ -585,7 +586,8 @@
void putDirectUndefined(PropertyOffset offset) { locationForOffset(offset)->setUndefined(); }
JS_EXPORT_PRIVATE void putDirectNativeFunction(VM&, JSGlobalObject*, const PropertyName&, unsigned functionLength, NativeFunction, Intrinsic, unsigned attributes);
- void putDirectBuiltinFunction(VM&, JSGlobalObject*, const PropertyName&, FunctionExecutable*, unsigned attributes);
+ JSFunction* putDirectBuiltinFunction(VM&, JSGlobalObject*, const PropertyName&, FunctionExecutable*, unsigned attributes);
+ JSFunction* putDirectBuiltinFunctionWithoutTransition(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);