]>
git.saurik.com Git - apple/javascriptcore.git/blob - runtime/JSFunction.cpp
7fedad7cd22a428b1aa10489372357f0b2b5474e
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
, PassRefPtr
<Structure
> structure
, int length
, const Identifier
& name
, NativeFunction func
)
49 : Base(&exec
->globalData(), structure
, name
)
51 , m_body(FunctionBodyNode::createNativeThunk(&exec
->globalData()))
57 setNativeFunction(func
);
58 putDirect(exec
->propertyNames().length
, jsNumber(exec
, length
), DontDelete
| ReadOnly
| DontEnum
);
66 JSFunction::JSFunction(ExecState
* exec
, const Identifier
& name
, FunctionBodyNode
* body
, ScopeChainNode
* scopeChainNode
)
67 : Base(&exec
->globalData(), exec
->lexicalGlobalObject()->functionStructure(), name
)
70 setScopeChain(scopeChainNode
);
73 JSFunction::~JSFunction()
75 // JIT code for other functions may have had calls linked directly to the code for this function; these links
76 // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
77 // this memory is freed and may be reused (potentially for another, different JSFunction).
78 #if ENABLE(JIT_OPTIMIZE_CALL)
79 if (m_body
&& m_body
->isGenerated())
80 m_body
->generatedBytecode().unlinkCallers();
82 if (!isHostFunction())
83 scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too?
86 void JSFunction::mark()
90 if (!isHostFunction())
94 CallType
JSFunction::getCallData(CallData
& callData
)
96 if (isHostFunction()) {
97 callData
.native
.function
= nativeFunction();
100 callData
.js
.functionBody
= m_body
.get();
101 callData
.js
.scopeChain
= scopeChain().node();
105 JSValue
JSFunction::call(ExecState
* exec
, JSValue thisValue
, const ArgList
& args
)
107 ASSERT(!isHostFunction());
108 return exec
->interpreter()->execute(m_body
.get(), exec
, this, thisValue
.toThisObject(exec
), args
, scopeChain().node(), exec
->exceptionSlot());
111 JSValue
JSFunction::argumentsGetter(ExecState
* exec
, const Identifier
&, const PropertySlot
& slot
)
113 JSFunction
* thisObj
= asFunction(slot
.slotBase());
114 ASSERT(!thisObj
->isHostFunction());
115 return exec
->interpreter()->retrieveArguments(exec
, thisObj
);
118 JSValue
JSFunction::callerGetter(ExecState
* exec
, const Identifier
&, const PropertySlot
& slot
)
120 JSFunction
* thisObj
= asFunction(slot
.slotBase());
121 ASSERT(!thisObj
->isHostFunction());
122 return exec
->interpreter()->retrieveCaller(exec
, thisObj
);
125 JSValue
JSFunction::lengthGetter(ExecState
* exec
, const Identifier
&, const PropertySlot
& slot
)
127 JSFunction
* thisObj
= asFunction(slot
.slotBase());
128 ASSERT(!thisObj
->isHostFunction());
129 return jsNumber(exec
, thisObj
->m_body
->parameterCount());
132 bool JSFunction::getOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
)
134 if (isHostFunction())
135 return Base::getOwnPropertySlot(exec
, propertyName
, slot
);
137 if (propertyName
== exec
->propertyNames().prototype
) {
138 JSValue
* location
= getDirectLocation(propertyName
);
141 JSObject
* prototype
= new (exec
) JSObject(scopeChain().globalObject()->emptyObjectStructure());
142 prototype
->putDirect(exec
->propertyNames().constructor
, this, DontEnum
);
143 putDirect(exec
->propertyNames().prototype
, prototype
, DontDelete
);
144 location
= getDirectLocation(propertyName
);
147 slot
.setValueSlot(this, location
, offsetForLocation(location
));
150 if (propertyName
== exec
->propertyNames().arguments
) {
151 slot
.setCustom(this, argumentsGetter
);
155 if (propertyName
== exec
->propertyNames().length
) {
156 slot
.setCustom(this, lengthGetter
);
160 if (propertyName
== exec
->propertyNames().caller
) {
161 slot
.setCustom(this, callerGetter
);
165 return Base::getOwnPropertySlot(exec
, propertyName
, slot
);
168 void JSFunction::put(ExecState
* exec
, const Identifier
& propertyName
, JSValue value
, PutPropertySlot
& slot
)
170 if (isHostFunction()) {
171 Base::put(exec
, propertyName
, value
, slot
);
174 if (propertyName
== exec
->propertyNames().arguments
|| propertyName
== exec
->propertyNames().length
)
176 Base::put(exec
, propertyName
, value
, slot
);
179 bool JSFunction::deleteProperty(ExecState
* exec
, const Identifier
& propertyName
)
181 if (isHostFunction())
182 return Base::deleteProperty(exec
, propertyName
);
183 if (propertyName
== exec
->propertyNames().arguments
|| propertyName
== exec
->propertyNames().length
)
185 return Base::deleteProperty(exec
, propertyName
);
188 // ECMA 13.2.2 [[Construct]]
189 ConstructType
JSFunction::getConstructData(ConstructData
& constructData
)
191 if (isHostFunction())
192 return ConstructTypeNone
;
193 constructData
.js
.functionBody
= m_body
.get();
194 constructData
.js
.scopeChain
= scopeChain().node();
195 return ConstructTypeJS
;
198 JSObject
* JSFunction::construct(ExecState
* exec
, const ArgList
& args
)
200 ASSERT(!isHostFunction());
201 Structure
* structure
;
202 JSValue prototype
= get(exec
, exec
->propertyNames().prototype
);
203 if (prototype
.isObject())
204 structure
= asObject(prototype
)->inheritorID();
206 structure
= exec
->lexicalGlobalObject()->emptyObjectStructure();
207 JSObject
* thisObj
= new (exec
) JSObject(structure
);
209 JSValue result
= exec
->interpreter()->execute(m_body
.get(), exec
, this, thisObj
, args
, scopeChain().node(), exec
->exceptionSlot());
210 if (exec
->hadException() || !result
.isObject())
212 return asObject(result
);