summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/runtime/JSFunction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/runtime/JSFunction.cpp')
-rw-r--r--JavaScriptCore/runtime/JSFunction.cpp103
1 files changed, 66 insertions, 37 deletions
diff --git a/JavaScriptCore/runtime/JSFunction.cpp b/JavaScriptCore/runtime/JSFunction.cpp
index cba6795..7fcd037 100644
--- a/JavaScriptCore/runtime/JSFunction.cpp
+++ b/JavaScriptCore/runtime/JSFunction.cpp
@@ -28,8 +28,10 @@
#include "CodeBlock.h"
#include "CommonIdentifiers.h"
#include "CallFrame.h"
+#include "ExceptionHelpers.h"
#include "FunctionPrototype.h"
#include "JSGlobalObject.h"
+#include "JSNotAnObject.h"
#include "Interpreter.h"
#include "ObjectPrototype.h"
#include "Parser.h"
@@ -41,9 +43,16 @@ using namespace Unicode;
namespace JSC {
+EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState* exec)
+{
+ CodeBlock* codeBlock = exec->callerFrame()->codeBlock();
+ unsigned vPCIndex = codeBlock->bytecodeOffset(exec, exec->returnPC());
+ return throwVMError(exec, createNotAConstructorError(exec, exec->callee(), vPCIndex, codeBlock));
+}
+
ASSERT_CLASS_FITS_IN_CELL(JSFunction);
-const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };
+const ClassInfo JSFunction::info = { "Function", 0, 0, 0 };
bool JSFunction::isHostFunctionNonInline() const
{
@@ -53,17 +62,30 @@ bool JSFunction::isHostFunctionNonInline() const
JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure)
: Base(structure)
, m_executable(adoptRef(new VPtrHackExecutable()))
+ , m_scopeChain(NoScopeChain())
{
}
-JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func)
- : Base(&exec->globalData(), structure, name)
#if ENABLE(JIT)
- , m_executable(adoptRef(new NativeExecutable(exec)))
+JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, PassRefPtr<NativeExecutable> thunk)
+ : Base(globalObject, structure)
+ , m_executable(thunk)
+ , m_scopeChain(globalObject->globalScopeChain())
+{
+ putDirect(exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
+ putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
+}
#endif
+
+JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func)
+ : Base(globalObject, structure)
+#if ENABLE(JIT)
+ , m_executable(exec->globalData().getHostFunction(func))
+#endif
+ , m_scopeChain(globalObject->globalScopeChain())
{
+ putDirect(exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
#if ENABLE(JIT)
- setNativeFunction(func);
putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
#else
UNUSED_PARAM(length);
@@ -73,10 +95,12 @@ JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure,
}
JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode)
- : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), executable->name())
+ : Base(scopeChainNode->globalObject, scopeChainNode->globalObject->functionStructure())
, m_executable(executable)
+ , m_scopeChain(scopeChainNode)
{
- setScopeChain(scopeChainNode);
+ const Identifier& name = static_cast<FunctionExecutable*>(m_executable.get())->name();
+ putDirect(exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
}
JSFunction::~JSFunction()
@@ -89,39 +113,61 @@ JSFunction::~JSFunction()
if (!isHostFunction()) {
#if ENABLE(JIT_OPTIMIZE_CALL)
ASSERT(m_executable);
- if (jsExecutable()->isGenerated())
- jsExecutable()->generatedBytecode().unlinkCallers();
+ if (jsExecutable()->isGeneratedForCall())
+ jsExecutable()->generatedBytecodeForCall().unlinkCallers();
+ if (jsExecutable()->isGeneratedForConstruct())
+ jsExecutable()->generatedBytecodeForConstruct().unlinkCallers();
#endif
- scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too?
}
}
+const UString& JSFunction::name(ExecState* exec)
+{
+ return asString(getDirect(exec->globalData().propertyNames->name))->tryGetValue();
+}
+
+const UString JSFunction::displayName(ExecState* exec)
+{
+ JSValue displayName = getDirect(exec->globalData().propertyNames->displayName);
+
+ if (displayName && isJSString(&exec->globalData(), displayName))
+ return asString(displayName)->tryGetValue();
+
+ return UString::null();
+}
+
+const UString JSFunction::calculatedDisplayName(ExecState* exec)
+{
+ const UString explicitName = displayName(exec);
+
+ if (!explicitName.isEmpty())
+ return explicitName;
+
+ return name(exec);
+}
+
void JSFunction::markChildren(MarkStack& markStack)
{
Base::markChildren(markStack);
if (!isHostFunction()) {
jsExecutable()->markAggregate(markStack);
- scopeChain().markAggregate(markStack);
+ scope().markAggregate(markStack);
}
}
CallType JSFunction::getCallData(CallData& callData)
{
+#if ENABLE(JIT)
if (isHostFunction()) {
callData.native.function = nativeFunction();
return CallTypeHost;
}
+#endif
callData.js.functionExecutable = jsExecutable();
- callData.js.scopeChain = scopeChain().node();
+ callData.js.scopeChain = scope().node();
return CallTypeJS;
}
-JSValue JSFunction::call(ExecState* exec, JSValue thisValue, const ArgList& args)
-{
- ASSERT(!isHostFunction());
- return exec->interpreter()->execute(jsExecutable(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot());
-}
-
JSValue JSFunction::argumentsGetter(ExecState* exec, JSValue slotBase, const Identifier&)
{
JSFunction* thisObj = asFunction(slotBase);
@@ -152,7 +198,7 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN
JSValue* location = getDirectLocation(propertyName);
if (!location) {
- JSObject* prototype = new (exec) JSObject(scopeChain().globalObject()->emptyObjectStructure());
+ JSObject* prototype = new (exec) JSObject(scope().globalObject()->emptyObjectStructure());
prototype->putDirect(exec->propertyNames().constructor, this, DontEnum);
putDirect(exec->propertyNames().prototype, prototype, DontDelete);
location = getDirectLocation(propertyName);
@@ -245,25 +291,8 @@ ConstructType JSFunction::getConstructData(ConstructData& constructData)
if (isHostFunction())
return ConstructTypeNone;
constructData.js.functionExecutable = jsExecutable();
- constructData.js.scopeChain = scopeChain().node();
+ constructData.js.scopeChain = scope().node();
return ConstructTypeJS;
}
-JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)
-{
- ASSERT(!isHostFunction());
- Structure* structure;
- JSValue prototype = get(exec, exec->propertyNames().prototype);
- if (prototype.isObject())
- structure = asObject(prototype)->inheritorID();
- else
- structure = exec->lexicalGlobalObject()->emptyObjectStructure();
- JSObject* thisObj = new (exec) JSObject(structure);
-
- JSValue result = exec->interpreter()->execute(jsExecutable(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot());
- if (exec->hadException() || !result.isObject())
- return thisObj;
- return asObject(result);
-}
-
} // namespace JSC