diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSFunction.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSFunction.cpp | 40 |
1 files changed, 17 insertions, 23 deletions
diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp index 2ade441..dbfc606 100644 --- a/Source/JavaScriptCore/runtime/JSFunction.cpp +++ b/Source/JavaScriptCore/runtime/JSFunction.cpp @@ -56,16 +56,16 @@ bool JSFunction::isHostFunctionNonInline() const return isHostFunction(); } -JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure) +JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure, VPtrHackExecutable* executable) : Base(structure) - , m_executable(adoptRef(new VPtrHackExecutable())) { ASSERT(inherits(&s_info)); + m_executable.setWithoutWriteBarrier(executable); } -JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, PassRefPtr<NativeExecutable> thunk) +JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeExecutable* thunk) : Base(globalObject, structure) - , m_executable(thunk) + , m_executable(exec->globalData(), this, thunk) , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain()) { ASSERT(inherits(&s_info)); @@ -75,17 +75,20 @@ JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPas JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func) : Base(globalObject, structure) - , m_executable(exec->globalData().getHostFunction(func)) , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain()) { ASSERT(inherits(&s_info)); + // We separate out intialisation from setting the executable + // as getHostFunction may perform a GC allocation, so we have to be able to + // mark ourselves safely + m_executable.set(exec->globalData(), this, exec->globalData().getHostFunction(func)); putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum); putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum); } -JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode) +JSFunction::JSFunction(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChainNode) : Base(scopeChainNode->globalObject.get(), scopeChainNode->globalObject->functionStructure()) - , m_executable(executable) + , m_executable(exec->globalData(), this, executable) , m_scopeChain(exec->globalData(), this, scopeChainNode) { ASSERT(inherits(&s_info)); @@ -96,19 +99,6 @@ JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> ex 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 - } } static const char* StrictModeCallerAccessError = "Cannot access caller property of a strict mode function"; @@ -148,9 +138,13 @@ const UString JSFunction::calculatedDisplayName(ExecState* exec) void JSFunction::markChildren(MarkStack& markStack) { Base::markChildren(markStack); - if (!isHostFunction()) { - jsExecutable()->markAggregate(markStack); - markStack.append(&m_scopeChain); + + markStack.append(&m_scopeChain); + if (m_executable) { + // Delightful race condition: m_executable may not have been initialised + // if this is a host function, as the executable isn't necessarily created + // until after the function has been allocated. + markStack.append(&m_executable); } } |