46
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)
48
bool JSFunction::isHostFunctionNonInline() const
50
return isHostFunction();
53
JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure)
55
, m_executable(adoptRef(new VPtrHackExecutable()))
59
JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func)
60
: Base(&exec->globalData(), structure, name)
62
, m_executable(adoptRef(new NativeExecutable(exec)))
66
setNativeFunction(func);
67
putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
75
JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode)
76
: Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), executable->name())
77
, m_executable(executable)
79
setScopeChain(scopeChainNode);
55
82
JSFunction::~JSFunction()
58
84
// JIT code for other functions may have had calls linked directly to the code for this function; these links
59
85
// are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
60
86
// 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();
87
if (!isHostFunction()) {
88
#if ENABLE(JIT_OPTIMIZE_CALL)
90
if (jsExecutable()->isGenerated())
91
jsExecutable()->generatedBytecode().unlinkCallers();
93
scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too?
66
void JSFunction::mark()
97
void JSFunction::markChildren(MarkStack& markStack)
99
Base::markChildren(markStack);
100
if (!isHostFunction()) {
101
jsExecutable()->markAggregate(markStack);
102
scopeChain().markAggregate(markStack);
73
106
CallType JSFunction::getCallData(CallData& callData)
75
callData.js.functionBody = m_body.get();
76
callData.js.scopeChain = m_scopeChain.node();
108
if (isHostFunction()) {
109
callData.native.function = nativeFunction();
112
callData.js.functionExecutable = jsExecutable();
113
callData.js.scopeChain = scopeChain().node();
77
114
return CallTypeJS;
80
JSValuePtr JSFunction::call(ExecState* exec, JSValuePtr thisValue, const ArgList& args)
117
JSValue JSFunction::call(ExecState* exec, JSValue thisValue, const ArgList& args)
82
return exec->interpreter()->execute(m_body.get(), exec, this, thisValue->toThisObject(exec), args, m_scopeChain.node(), exec->exceptionSlot());
119
ASSERT(!isHostFunction());
120
return exec->interpreter()->execute(jsExecutable(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot());
85
JSValuePtr JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
123
JSValue JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
87
125
JSFunction* thisObj = asFunction(slot.slotBase());
126
ASSERT(!thisObj->isHostFunction());
88
127
return exec->interpreter()->retrieveArguments(exec, thisObj);
91
JSValuePtr JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
130
JSValue JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
93
132
JSFunction* thisObj = asFunction(slot.slotBase());
133
ASSERT(!thisObj->isHostFunction());
94
134
return exec->interpreter()->retrieveCaller(exec, thisObj);
97
JSValuePtr JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
137
JSValue JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
99
139
JSFunction* thisObj = asFunction(slot.slotBase());
100
return jsNumber(exec, thisObj->m_body->parameterCount());
140
ASSERT(!thisObj->isHostFunction());
141
return jsNumber(exec, thisObj->jsExecutable()->parameterCount());
103
144
bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
146
if (isHostFunction())
147
return Base::getOwnPropertySlot(exec, propertyName, slot);
105
149
if (propertyName == exec->propertyNames().prototype) {
106
JSValuePtr* location = getDirectLocation(propertyName);
150
JSValue* location = getDirectLocation(propertyName);
109
JSObject* prototype = new (exec) JSObject(m_scopeChain.globalObject()->emptyObjectStructure());
153
JSObject* prototype = new (exec) JSObject(scopeChain().globalObject()->emptyObjectStructure());
110
154
prototype->putDirect(exec->propertyNames().constructor, this, DontEnum);
111
155
putDirect(exec->propertyNames().prototype, prototype, DontDelete);
112
156
location = getDirectLocation(propertyName);
133
177
return Base::getOwnPropertySlot(exec, propertyName, slot);
136
void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot)
180
bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
182
if (isHostFunction())
183
return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
185
if (propertyName == exec->propertyNames().prototype) {
187
getOwnPropertySlot(exec, propertyName, slot);
188
return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
191
if (propertyName == exec->propertyNames().arguments) {
192
descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete);
196
if (propertyName == exec->propertyNames().length) {
197
descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete);
201
if (propertyName == exec->propertyNames().caller) {
202
descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete);
206
return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
209
void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
211
if (isHostFunction()) {
212
Base::put(exec, propertyName, value, slot);
138
215
if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
140
217
Base::put(exec, propertyName, value, slot);
150
229
// ECMA 13.2.2 [[Construct]]
151
230
ConstructType JSFunction::getConstructData(ConstructData& constructData)
153
constructData.js.functionBody = m_body.get();
154
constructData.js.scopeChain = m_scopeChain.node();
232
if (isHostFunction())
233
return ConstructTypeNone;
234
constructData.js.functionExecutable = jsExecutable();
235
constructData.js.scopeChain = scopeChain().node();
155
236
return ConstructTypeJS;
158
239
JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)
241
ASSERT(!isHostFunction());
160
242
Structure* structure;
161
JSValuePtr prototype = get(exec, exec->propertyNames().prototype);
162
if (prototype->isObject())
243
JSValue prototype = get(exec, exec->propertyNames().prototype);
244
if (prototype.isObject())
163
245
structure = asObject(prototype)->inheritorID();
165
247
structure = exec->lexicalGlobalObject()->emptyObjectStructure();
166
248
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())
250
JSValue result = exec->interpreter()->execute(jsExecutable(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot());
251
if (exec->hadException() || !result.isObject())
171
253
return asObject(result);