From 103439f4c8a70740d6475af1b1b58deede12d2c3 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Thu, 9 Jul 2009 10:20:20 +0200 Subject: create a new frame when executing native getter/setter functions Frames are created when calling JS functions, so they should be when calling native functions as well. This makes QScriptContext behave correctly in these cases (see getSetProperty autotest). --- .../webkit/JavaScriptCore/runtime/CallData.cpp | 23 ++++++++++++++++++++-- .../webkit/JavaScriptCore/runtime/PropertySlot.cpp | 19 ++++++++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.cpp index 62e42fe..0579b27 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/CallData.cpp @@ -25,6 +25,8 @@ #include "config.h" #include "CallData.h" +#include "ExceptionHelpers.h" +#include "Interpreter.h" #include "JSFunction.h" @@ -32,8 +34,25 @@ namespace JSC { JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args) { - if (callType == CallTypeHost) - return callData.native.function(exec, asObject(functionObject), thisValue, args); + if (callType == CallTypeHost) { + ScopeChainNode* scopeChain = exec->scopeChain(); + Interpreter *interp = exec->interpreter(); + Register *oldEnd = interp->registerFile().end(); + int argc = 1 + args.size(); // implicit "this" parameter + if (!interp->registerFile().grow(oldEnd + argc + RegisterFile::CallFrameHeaderSize)) + return createStackOverflowError(exec); + CallFrame* newCallFrame = CallFrame::create(oldEnd); + newCallFrame[0] = thisValue; + size_t dst = 0; + ArgList::const_iterator it; + for (it = args.begin(); it != args.end(); ++it) + newCallFrame[++dst] = *it; + newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize; + newCallFrame->init(0, /*vPC=*/0, scopeChain, exec, 0, argc, asObject(functionObject)); + JSValue result = callData.native.function(newCallFrame, asObject(functionObject), thisValue, args); + interp->registerFile().shrink(oldEnd); + return result; + } ASSERT(callType == CallTypeJS); // FIXME: Can this be done more efficiently using the callData? return asFunction(functionObject)->call(exec, thisValue, args); diff --git a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertySlot.cpp b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertySlot.cpp index 36fa5d8..e0a1b5d 100644 --- a/src/3rdparty/webkit/JavaScriptCore/runtime/PropertySlot.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/runtime/PropertySlot.cpp @@ -19,6 +19,8 @@ */ #include "config.h" +#include "ExceptionHelpers.h" +#include "Interpreter.h" #include "PropertySlot.h" #include "JSFunction.h" @@ -35,8 +37,21 @@ JSValue PropertySlot::functionGetter(ExecState* exec, const Identifier&, const P CallData callData; CallType callType = slot.m_data.getterFunc->getCallData(callData); - if (callType == CallTypeHost) - return callData.native.function(exec, slot.m_data.getterFunc, slot.slotBase(), exec->emptyList()); + if (callType == CallTypeHost) { + ScopeChainNode* scopeChain = exec->scopeChain(); + Interpreter *interp = exec->interpreter(); + Register *oldEnd = interp->registerFile().end(); + int argc = 1; // implicit "this" parameter + if (!interp->registerFile().grow(oldEnd + argc + RegisterFile::CallFrameHeaderSize)) + return createStackOverflowError(exec); + JSC::CallFrame* newCallFrame = JSC::CallFrame::create(oldEnd); + newCallFrame[0] = slot.slotBase(); // this + newCallFrame += argc + JSC::RegisterFile::CallFrameHeaderSize; + newCallFrame->init(0, /*vPC=*/0, scopeChain, exec, 0, argc, slot.m_data.getterFunc); + JSValue result = callData.native.function(newCallFrame, slot.m_data.getterFunc, slot.slotBase(), exec->emptyList()); + interp->registerFile().shrink(oldEnd); + return result; + } ASSERT(callType == CallTypeJS); // FIXME: Can this be done more efficiently using the callData? return static_cast(slot.m_data.getterFunc)->call(exec, slot.slotBase(), exec->emptyList()); -- cgit v0.12