]>
git.saurik.com Git - apple/javascriptcore.git/blob - runtime/JSFunction.cpp
2 * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5 * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6 * Copyright (C) 2007 Maks Orlovich
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
26 #include "JSFunction.h"
28 #include "CodeBlock.h"
29 #include "CommonIdentifiers.h"
30 #include "CallFrame.h"
31 #include "FunctionPrototype.h"
32 #include "JSGlobalObject.h"
33 #include "Interpreter.h"
34 #include "ObjectPrototype.h"
36 #include "PropertyNameArray.h"
37 #include "ScopeChainMark.h"
40 using namespace Unicode
;
44 ASSERT_CLASS_FITS_IN_CELL(JSFunction
);
46 const ClassInfo
JSFunction::info
= { "Function", &InternalFunction::info
, 0, 0 };
48 JSFunction::JSFunction(ExecState
* exec
, const Identifier
& name
, FunctionBodyNode
* body
, ScopeChainNode
* scopeChainNode
)
49 : Base(&exec
->globalData(), exec
->lexicalGlobalObject()->functionStructure(), name
)
51 , m_scopeChain(scopeChainNode
)
55 JSFunction::~JSFunction()
58 // JIT code for other functions may have had calls linked directly to the code for this function; these links
59 // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
60 // this memory is freed and may be reused (potentially for another, different JSFunction).
61 if (m_body
&& m_body
->isGenerated())
62 m_body
->generatedBytecode().unlinkCallers();
66 void JSFunction::mark()
73 CallType
JSFunction::getCallData(CallData
& callData
)
75 callData
.js
.functionBody
= m_body
.get();
76 callData
.js
.scopeChain
= m_scopeChain
.node();
80 JSValuePtr
JSFunction::call(ExecState
* exec
, JSValuePtr thisValue
, const ArgList
& args
)
82 return exec
->interpreter()->execute(m_body
.get(), exec
, this, thisValue
.toThisObject(exec
), args
, m_scopeChain
.node(), exec
->exceptionSlot());
85 JSValuePtr
JSFunction::argumentsGetter(ExecState
* exec
, const Identifier
&, const PropertySlot
& slot
)
87 JSFunction
* thisObj
= asFunction(slot
.slotBase());
88 return exec
->interpreter()->retrieveArguments(exec
, thisObj
);
91 JSValuePtr
JSFunction::callerGetter(ExecState
* exec
, const Identifier
&, const PropertySlot
& slot
)
93 JSFunction
* thisObj
= asFunction(slot
.slotBase());
94 return exec
->interpreter()->retrieveCaller(exec
, thisObj
);
97 JSValuePtr
JSFunction::lengthGetter(ExecState
* exec
, const Identifier
&, const PropertySlot
& slot
)
99 JSFunction
* thisObj
= asFunction(slot
.slotBase());
100 return jsNumber(exec
, thisObj
->m_body
->parameterCount());
103 bool JSFunction::getOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
105 if (propertyName
== exec
->propertyNames().prototype
) {
106 JSValuePtr
* location
= getDirectLocation(propertyName
);
109 JSObject
* prototype
= new (exec
) JSObject(m_scopeChain
.globalObject()->emptyObjectStructure());
110 prototype
->putDirect(exec
->propertyNames().constructor
, this, DontEnum
);
111 putDirect(exec
->propertyNames().prototype
, prototype
, DontDelete
);
112 location
= getDirectLocation(propertyName
);
115 slot
.setValueSlot(this, location
, offsetForLocation(location
));
118 if (propertyName
== exec
->propertyNames().arguments
) {
119 slot
.setCustom(this, argumentsGetter
);
123 if (propertyName
== exec
->propertyNames().length
) {
124 slot
.setCustom(this, lengthGetter
);
128 if (propertyName
== exec
->propertyNames().caller
) {
129 slot
.setCustom(this, callerGetter
);
133 return Base::getOwnPropertySlot(exec
, propertyName
, slot
);
136 void JSFunction::put(ExecState
* exec
, const Identifier
& propertyName
, JSValuePtr value
, PutPropertySlot
& slot
)
138 if (propertyName
== exec
->propertyNames().arguments
|| propertyName
== exec
->propertyNames().length
)
140 Base::put(exec
, propertyName
, value
, slot
);
143 bool JSFunction::deleteProperty(ExecState
* exec
, const Identifier
& propertyName
)
145 if (propertyName
== exec
->propertyNames().arguments
|| propertyName
== exec
->propertyNames().length
)
147 return Base::deleteProperty(exec
, propertyName
);
150 // ECMA 13.2.2 [[Construct]]
151 ConstructType
JSFunction::getConstructData(ConstructData
& constructData
)
153 constructData
.js
.functionBody
= m_body
.get();
154 constructData
.js
.scopeChain
= m_scopeChain
.node();
155 return ConstructTypeJS
;
158 JSObject
* JSFunction::construct(ExecState
* exec
, const ArgList
& args
)
160 Structure
* structure
;
161 JSValuePtr prototype
= get(exec
, exec
->propertyNames().prototype
);
162 if (prototype
.isObject())
163 structure
= asObject(prototype
)->inheritorID();
165 structure
= exec
->lexicalGlobalObject()->emptyObjectStructure();
166 JSObject
* thisObj
= new (exec
) JSObject(structure
);
168 JSValuePtr result
= exec
->interpreter()->execute(m_body
.get(), exec
, this, thisObj
, args
, m_scopeChain
.node(), exec
->exceptionSlot());
169 if (exec
->hadException() || !result
.isObject())
171 return asObject(result
);