JSFunction::~JSFunction() { // JIT code for other functions may have had calls linked directly to the code for this function; these links // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once // this memory is freed and may be reused (potentially for another, different JSFunction). if (!isHostFunction()) { #if ENABLE(JIT_OPTIMIZE_CALL) ASSERT(m_executable); if (jsExecutable()->isGenerated()) jsExecutable()->generatedBytecode().unlinkCallers(); #endif scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too? } }
bool AJFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { if (isHostFunction()) return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); if (propertyName == exec->propertyNames().prototype) { PropertySlot slot; getOwnPropertySlot(exec, propertyName, slot); return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); } if (propertyName == exec->propertyNames().arguments) { descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete); return true; } if (propertyName == exec->propertyNames().length) { descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete); return true; } if (propertyName == exec->propertyNames().caller) { descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete); return true; } return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); }
// ECMA 13.2.2 [[Construct]] ConstructType AJFunction::getConstructData(ConstructData& constructData) { if (isHostFunction()) return ConstructTypeNone; constructData.js.functionExecutable = jsExecutable(); constructData.js.scopeChain = scopeChain().node(); return ConstructTypeJS; }
void AJFunction::markChildren(MarkStack& markStack) { Base::markChildren(markStack); if (!isHostFunction()) { jsExecutable()->markAggregate(markStack); scopeChain().markAggregate(markStack); } }
JSFunction::~JSFunction() { ASSERT(vptr() == JSGlobalData::jsFunctionVPtr); // JIT code for other functions may have had calls linked directly to the code for this function; these links // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once // this memory is freed and may be reused (potentially for another, different JSFunction). if (!isHostFunction()) { #if ENABLE(JIT_OPTIMIZE_CALL) ASSERT(m_executable); if (jsExecutable()->isGeneratedForCall()) jsExecutable()->generatedBytecodeForCall().unlinkCallers(); if (jsExecutable()->isGeneratedForConstruct()) jsExecutable()->generatedBytecodeForConstruct().unlinkCallers(); #endif } }
bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { if (isHostFunction()) return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); if (propertyName == exec->propertyNames().prototype) { PropertySlot slot; getOwnPropertySlotVirtual(exec, propertyName, slot); return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); } if (propertyName == exec->propertyNames().arguments) { if (jsExecutable()->isStrictMode()) { bool result = Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); if (!result) { initializeGetterSetterProperty(exec, propertyName, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter); result = Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); ASSERT(result); } return result; } descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete); return true; } if (propertyName == exec->propertyNames().length) { descriptor.setDescriptor(jsNumber(jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete); return true; } if (propertyName == exec->propertyNames().caller) { if (jsExecutable()->isStrictMode()) { bool result = Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); if (!result) { initializeGetterSetterProperty(exec, propertyName, globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Getter | Setter); result = Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); ASSERT(result); } return result; } descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete); return true; } return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); }
CallType AJFunction::getCallData(CallData& callData) { if (isHostFunction()) { callData.native.function = nativeFunction(); return CallTypeHost; } callData.js.functionExecutable = jsExecutable(); callData.js.scopeChain = scopeChain().node(); return CallTypeJS; }
CallType JSFunction::getCallData(CallData& callData) { #if ENABLE(JIT) if (isHostFunction()) { callData.native.function = nativeFunction(); return CallTypeHost; } #endif callData.js.functionExecutable = jsExecutable(); callData.js.scopeChain = scope().node(); return CallTypeJS; }
const String JSFunction::calculatedDisplayName(ExecState* exec) { const String explicitName = displayName(exec); if (!explicitName.isEmpty()) return explicitName; const String actualName = name(exec); if (!actualName.isEmpty() || isHostFunction()) return actualName; return jsExecutable()->inferredName().string(); }
AJObject* AJFunction::construct(ExecState* exec, const ArgList& args) { ASSERT(!isHostFunction()); Structure* structure; AJValue prototype = get(exec, exec->propertyNames().prototype); if (prototype.isObject()) structure = asObject(prototype)->inheritorID(); else structure = exec->lexicalGlobalObject()->emptyObjectStructure(); AJObject* thisObj = new (exec) AJObject(structure); AJValue result = exec->interpreter()->execute(jsExecutable(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot()); if (exec->hadException() || !result.isObject()) return thisObj; return asObject(result); }
AJValue AJFunction::call(ExecState* exec, AJValue thisValue, const ArgList& args) { ASSERT(!isHostFunction()); return exec->interpreter()->execute(jsExecutable(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot()); }
const SourceCode* JSFunction::sourceCode() const { if (isHostFunction()) return 0; return &jsExecutable()->source(); }
bool JSFunction::isBuiltinFunction() const { return !isHostFunction() && jsExecutable()->isBuiltinFunction(); }