source: webkit/trunk/JavaScriptCore/runtime/Operations.h@ 61623

Last change on this file since 61623 was 60392, checked in by [email protected], 15 years ago

JavaScriptCore: Simplified the host calling convention.

Reviewed by Sam Weinig, Gavin Barraclough, Oliver Hunt.

22.5% speedup on 32-bit host function calls. 9.5% speedup on 64-bit host
function calls.

No change on SunSpider.

All JS calls (but not constructs, yet) now go through the normal JS
calling convention via the RegisterFile. As a result, the host calling
convention, which used to be this

JSValue (JSC_HOST_CALL *NativeFunction)(ExecState*, JSObject*, JSValue thisValue, const ArgList&)


is now this

JSValue (JSC_HOST_CALL *NativeFunction)(ExecState*)


Callee, 'this', and argument access all hapen relative to the ExecState*,
which is a pointer into the RegisterFile.

This patch comes in two parts.

PART ONE: Functional code changes.

  • wtf/Platform.h: Disabled optimized calls on platforms I didn't test.

We can re-enable once we verify that host calls on these platforms are
correct.

  • debugger/DebuggerCallFrame.cpp:

(JSC::DebuggerCallFrame::functionName):
(JSC::DebuggerCallFrame::calculatedFunctionName): Updated for change to
ExecState::callee().

(JSC::DebuggerCallFrame::thisObject): Updated for removal of ExecState::thisValue().

  • interpreter/CallFrame.cpp:
  • interpreter/CallFrame.h:

(JSC::ExecState::callee):
(JSC::ExecState::scopeChain):
(JSC::ExecState::init): Changed callee() to be JSObject* instead of
JSFunction* -- now, it might be some other callable host object.

(JSC::ExecState::hostThisRegister):
(JSC::ExecState::hostThisValue):
(JSC::ExecState::argumentCount):
(JSC::ExecState::argumentCountIncludingThis):
(JSC::ExecState::argument):
(JSC::ExecState::setArgumentCountIncludingThis):
(JSC::ExecState::setCallee): Added convenient accessors for arguments
from within a host function. Removed thisValue() because it was too
tempting to use incorrectly, and it only had one or two clients, anyway.

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::callEval): Updated for removal of ExecState::thisValue().

(JSC::Interpreter::throwException): Be sure to shrink the register file
before invoking the exception handler, to reduce the chances that the
handler will re-throw in the case of stack overflow. (Re-throwing is now
more likely than it used to be, since standardizing the calling convention
implicitly added stack overflow checks to some places where they used to be missing.)

(JSC::Interpreter::execute): Clarified the scope of DynamicGlobalObjectScope.
Updated for CallFrame::init API change.

(JSC::Interpreter::executeCall): Clarified scope of DynamicGlobalObjectScope.
Updated for CallFrame::init API change. Added support for calling a host
function.

(JSC::Interpreter::executeConstruct): Clarified scope of DynamicGlobalObjectScope.
Updated for CallFrame::init API change.

(JSC::Interpreter::prepareForRepeatCall): Updated for CallFrame::init API change.

(JSC::Interpreter::privateExecute): Updated for CallFrame::init API change.
Added some explicit JSValue(JSObject*) initialization, since relaxing
the JSFunction* restriction on callee has made register types more ambiguous.
Removed toThisObject() conversion, since all callees do it themselves now.
Updated host function call for new host function signature. Updated for
change to ExecState::argumentCount() API.

  • interpreter/Register.h:

(JSC::Register::):
(JSC::Register::operator=):
(JSC::Register::function): Changed callee() to be JSObject* instead of
JSFunction* -- now, it might be some other callable host object.

  • jit/JITOpcodes.cpp:

(JSC::JIT::privateCompileCTINativeCall):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::privateCompileCTINativeCall): Deleted a bunch of code that
set up the arguments to host functions -- all but one of the arguments
are gone now. This is the actual optimization.

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION): Updated for ExecState and Register API
changes noted above. Removed toThisObject() conversion, since all callees
do it themselves now.

  • runtime/ArgList.h:

(JSC::ArgList::ArgList): ArgList is getting close to unused. Added a
temporary shim for converting from ExecState* to ArgList where it's still
necessary.

  • runtime/Arguments.h:

(JSC::Arguments::getArgumentsData):
(JSC::Arguments::Arguments): Updated for ExecState and Register API
changes noted above.

  • runtime/CallData.cpp:

(JSC::call): Changed call always to call Interpreter::executeCall, even
for host functions. This ensures that the normal calling convention is
set up in the RegsiterFile when calling from C++ to host function.

  • runtime/CallData.h: Changed host function signature as described above.
  • runtime/ConstructData.cpp:

(JSC::construct): Moved JSFunction::construct code here so I could nix
JSFunction::call and JSFunction::call. We want a JSFunction-agnostic
way to call and construct, so that everything works naturally for non-
JSFunction objects.

  • runtime/JSFunction.cpp:

(JSC::callHostFunctionAsConstructor):

  • runtime/JSFunction.h: Updated for ExecState and Register API changes

noted above. Nixed JSFunction::call and JSFunction::construct, noted above.

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init): Ditto.

PART TWO: Global search and replace.

In the areas below, I used global search-and-replace to change

(ExecState*, JSObject*, JSValue, const ArgList&) => (ExecState*)
args.size() => exec->argumentCount()
args.at(i) => exec->argument(i)

  • API/JSCallbackFunction.cpp:

(JSC::JSCallbackFunction::call):

  • API/JSCallbackFunction.h:
  • API/JSCallbackObject.h:
  • API/JSCallbackObjectFunctions.h:

(JSC::::call):

(functionPrint):
(functionDebug):
(functionGC):
(functionVersion):
(functionRun):
(functionLoad):
(functionCheckSyntax):
(functionSetSamplingFlags):
(functionClearSamplingFlags):
(functionReadline):
(functionQuit):

  • runtime/ArrayConstructor.cpp:

(JSC::callArrayConstructor):
(JSC::arrayConstructorIsArray):

  • runtime/ArrayPrototype.cpp:

(JSC::arrayProtoFuncToString):
(JSC::arrayProtoFuncToLocaleString):
(JSC::arrayProtoFuncJoin):
(JSC::arrayProtoFuncConcat):
(JSC::arrayProtoFuncPop):
(JSC::arrayProtoFuncPush):
(JSC::arrayProtoFuncReverse):
(JSC::arrayProtoFuncShift):
(JSC::arrayProtoFuncSlice):
(JSC::arrayProtoFuncSort):
(JSC::arrayProtoFuncSplice):
(JSC::arrayProtoFuncUnShift):
(JSC::arrayProtoFuncFilter):
(JSC::arrayProtoFuncMap):
(JSC::arrayProtoFuncEvery):
(JSC::arrayProtoFuncForEach):
(JSC::arrayProtoFuncSome):
(JSC::arrayProtoFuncReduce):
(JSC::arrayProtoFuncReduceRight):
(JSC::arrayProtoFuncIndexOf):
(JSC::arrayProtoFuncLastIndexOf):

  • runtime/BooleanConstructor.cpp:

(JSC::callBooleanConstructor):

  • runtime/BooleanPrototype.cpp:

(JSC::booleanProtoFuncToString):
(JSC::booleanProtoFuncValueOf):

  • runtime/DateConstructor.cpp:

(JSC::callDate):
(JSC::dateParse):
(JSC::dateNow):
(JSC::dateUTC):

  • runtime/DatePrototype.cpp:

(JSC::formatLocaleDate):
(JSC::fillStructuresUsingTimeArgs):
(JSC::fillStructuresUsingDateArgs):
(JSC::dateProtoFuncToString):
(JSC::dateProtoFuncToUTCString):
(JSC::dateProtoFuncToISOString):
(JSC::dateProtoFuncToDateString):
(JSC::dateProtoFuncToTimeString):
(JSC::dateProtoFuncToLocaleString):
(JSC::dateProtoFuncToLocaleDateString):
(JSC::dateProtoFuncToLocaleTimeString):
(JSC::dateProtoFuncGetTime):
(JSC::dateProtoFuncGetFullYear):
(JSC::dateProtoFuncGetUTCFullYear):
(JSC::dateProtoFuncToGMTString):
(JSC::dateProtoFuncGetMonth):
(JSC::dateProtoFuncGetUTCMonth):
(JSC::dateProtoFuncGetDate):
(JSC::dateProtoFuncGetUTCDate):
(JSC::dateProtoFuncGetDay):
(JSC::dateProtoFuncGetUTCDay):
(JSC::dateProtoFuncGetHours):
(JSC::dateProtoFuncGetUTCHours):
(JSC::dateProtoFuncGetMinutes):
(JSC::dateProtoFuncGetUTCMinutes):
(JSC::dateProtoFuncGetSeconds):
(JSC::dateProtoFuncGetUTCSeconds):
(JSC::dateProtoFuncGetMilliSeconds):
(JSC::dateProtoFuncGetUTCMilliseconds):
(JSC::dateProtoFuncGetTimezoneOffset):
(JSC::dateProtoFuncSetTime):
(JSC::setNewValueFromTimeArgs):
(JSC::setNewValueFromDateArgs):
(JSC::dateProtoFuncSetMilliSeconds):
(JSC::dateProtoFuncSetUTCMilliseconds):
(JSC::dateProtoFuncSetSeconds):
(JSC::dateProtoFuncSetUTCSeconds):
(JSC::dateProtoFuncSetMinutes):
(JSC::dateProtoFuncSetUTCMinutes):
(JSC::dateProtoFuncSetHours):
(JSC::dateProtoFuncSetUTCHours):
(JSC::dateProtoFuncSetDate):
(JSC::dateProtoFuncSetUTCDate):
(JSC::dateProtoFuncSetMonth):
(JSC::dateProtoFuncSetUTCMonth):
(JSC::dateProtoFuncSetFullYear):
(JSC::dateProtoFuncSetUTCFullYear):
(JSC::dateProtoFuncSetYear):
(JSC::dateProtoFuncGetYear):
(JSC::dateProtoFuncToJSON):

  • runtime/ErrorConstructor.cpp:

(JSC::callErrorConstructor):

  • runtime/ErrorPrototype.cpp:

(JSC::errorProtoFuncToString):

  • runtime/FunctionConstructor.cpp:

(JSC::callFunctionConstructor):

  • runtime/FunctionPrototype.cpp:

(JSC::callFunctionPrototype):
(JSC::functionProtoFuncToString):
(JSC::functionProtoFuncApply):
(JSC::functionProtoFuncCall):

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::encode):
(JSC::decode):
(JSC::globalFuncEval):
(JSC::globalFuncParseInt):
(JSC::globalFuncParseFloat):
(JSC::globalFuncIsNaN):
(JSC::globalFuncIsFinite):
(JSC::globalFuncDecodeURI):
(JSC::globalFuncDecodeURIComponent):
(JSC::globalFuncEncodeURI):
(JSC::globalFuncEncodeURIComponent):
(JSC::globalFuncEscape):
(JSC::globalFuncUnescape):
(JSC::globalFuncJSCPrint):

  • runtime/JSGlobalObjectFunctions.h:
  • runtime/JSONObject.cpp:

(JSC::JSONProtoFuncParse):
(JSC::JSONProtoFuncStringify):

  • runtime/JSString.h:
  • runtime/MathObject.cpp:

(JSC::mathProtoFuncAbs):
(JSC::mathProtoFuncACos):
(JSC::mathProtoFuncASin):
(JSC::mathProtoFuncATan):
(JSC::mathProtoFuncATan2):
(JSC::mathProtoFuncCeil):
(JSC::mathProtoFuncCos):
(JSC::mathProtoFuncExp):
(JSC::mathProtoFuncFloor):
(JSC::mathProtoFuncLog):
(JSC::mathProtoFuncMax):
(JSC::mathProtoFuncMin):
(JSC::mathProtoFuncPow):
(JSC::mathProtoFuncRandom):
(JSC::mathProtoFuncRound):
(JSC::mathProtoFuncSin):
(JSC::mathProtoFuncSqrt):
(JSC::mathProtoFuncTan):

  • runtime/NativeErrorConstructor.cpp:

(JSC::callNativeErrorConstructor):

  • runtime/NumberConstructor.cpp:

(JSC::callNumberConstructor):

  • runtime/NumberPrototype.cpp:

(JSC::numberProtoFuncToString):
(JSC::numberProtoFuncToLocaleString):
(JSC::numberProtoFuncValueOf):
(JSC::numberProtoFuncToFixed):
(JSC::numberProtoFuncToExponential):
(JSC::numberProtoFuncToPrecision):

  • runtime/ObjectConstructor.cpp:

(JSC::callObjectConstructor):
(JSC::objectConstructorGetPrototypeOf):
(JSC::objectConstructorGetOwnPropertyDescriptor):
(JSC::objectConstructorGetOwnPropertyNames):
(JSC::objectConstructorKeys):
(JSC::objectConstructorDefineProperty):
(JSC::objectConstructorDefineProperties):
(JSC::objectConstructorCreate):

  • runtime/ObjectPrototype.cpp:

(JSC::objectProtoFuncValueOf):
(JSC::objectProtoFuncHasOwnProperty):
(JSC::objectProtoFuncIsPrototypeOf):
(JSC::objectProtoFuncDefineGetter):
(JSC::objectProtoFuncDefineSetter):
(JSC::objectProtoFuncLookupGetter):
(JSC::objectProtoFuncLookupSetter):
(JSC::objectProtoFuncPropertyIsEnumerable):
(JSC::objectProtoFuncToLocaleString):
(JSC::objectProtoFuncToString):

  • runtime/ObjectPrototype.h:
  • runtime/Operations.h:

(JSC::jsString):

  • runtime/RegExpConstructor.cpp:

(JSC::callRegExpConstructor):

  • runtime/RegExpObject.cpp:

(JSC::RegExpObject::test):
(JSC::RegExpObject::exec):
(JSC::callRegExpObject):
(JSC::RegExpObject::match):

  • runtime/RegExpObject.h:
  • runtime/RegExpPrototype.cpp:

(JSC::regExpProtoFuncTest):
(JSC::regExpProtoFuncExec):
(JSC::regExpProtoFuncCompile):
(JSC::regExpProtoFuncToString):

  • runtime/StringConstructor.cpp:

(JSC::stringFromCharCodeSlowCase):
(JSC::stringFromCharCode):
(JSC::callStringConstructor):

  • runtime/StringPrototype.cpp:

(JSC::stringProtoFuncReplace):
(JSC::stringProtoFuncToString):
(JSC::stringProtoFuncCharAt):
(JSC::stringProtoFuncCharCodeAt):
(JSC::stringProtoFuncConcat):
(JSC::stringProtoFuncIndexOf):
(JSC::stringProtoFuncLastIndexOf):
(JSC::stringProtoFuncMatch):
(JSC::stringProtoFuncSearch):
(JSC::stringProtoFuncSlice):
(JSC::stringProtoFuncSplit):
(JSC::stringProtoFuncSubstr):
(JSC::stringProtoFuncSubstring):
(JSC::stringProtoFuncToLowerCase):
(JSC::stringProtoFuncToUpperCase):
(JSC::stringProtoFuncLocaleCompare):
(JSC::stringProtoFuncBig):
(JSC::stringProtoFuncSmall):
(JSC::stringProtoFuncBlink):
(JSC::stringProtoFuncBold):
(JSC::stringProtoFuncFixed):
(JSC::stringProtoFuncItalics):
(JSC::stringProtoFuncStrike):
(JSC::stringProtoFuncSub):
(JSC::stringProtoFuncSup):
(JSC::stringProtoFuncFontcolor):
(JSC::stringProtoFuncFontsize):
(JSC::stringProtoFuncAnchor):
(JSC::stringProtoFuncLink):
(JSC::stringProtoFuncTrim):
(JSC::stringProtoFuncTrimLeft):
(JSC::stringProtoFuncTrimRight):

JavaScriptGlue: Simplified the host calling convention.

Reviewed by Sam Weinig, Gavin Barraclough, Oliver Hunt.

PART ONE: Functional code changes.

[ None in JavaScriptGlue ]

PART TWO: Global search and replace.

In the areas below, I used global search-and-replace to change

(ExecState*, JSObject*, JSValue, const ArgList&) => (ExecState*)
args.size() => exec->argumentCount()
args.at(i) => exec->argument(i)

  • JSObject.cpp:

(nativeCallFunction):

  • UserObjectImp.cpp:

(UserObjectImp::callAsFunction):

  • UserObjectImp.h:

WebCore: Simplified the host calling convention.

Reviewed by Sam Weinig, Gavin Barraclough, Oliver Hunt.

PART ONE: Functional code changes.

[ None in WebCore ]

PART TWO: Global search and replace.

In the areas below, I used global search-and-replace to change

(ExecState*, JSObject*, JSValue, const ArgList&) => (ExecState*)
args.size() => exec->argumentCount()
args.at(i) => exec->argument(i)

  • bindings/js/JSArrayBufferViewCustom.cpp:

(WebCore::JSArrayBufferView::slice):

  • bindings/js/JSArrayBufferViewHelper.h:

(WebCore::setWebGLArrayHelper):

  • bindings/js/JSCanvasRenderingContext2DCustom.cpp:

(WebCore::JSCanvasRenderingContext2D::setFillColor):
(WebCore::JSCanvasRenderingContext2D::setStrokeColor):
(WebCore::JSCanvasRenderingContext2D::strokeRect):
(WebCore::JSCanvasRenderingContext2D::drawImage):
(WebCore::JSCanvasRenderingContext2D::drawImageFromRect):
(WebCore::JSCanvasRenderingContext2D::setShadow):
(WebCore::JSCanvasRenderingContext2D::createPattern):
(WebCore::JSCanvasRenderingContext2D::createImageData):
(WebCore::JSCanvasRenderingContext2D::putImageData):
(WebCore::JSCanvasRenderingContext2D::fillText):
(WebCore::JSCanvasRenderingContext2D::strokeText):

  • bindings/js/JSClipboardCustom.cpp:

(WebCore::JSClipboard::clearData):
(WebCore::JSClipboard::getData):
(WebCore::JSClipboard::setDragImage):

  • bindings/js/JSDOMApplicationCacheCustom.cpp:

(WebCore::JSDOMApplicationCache::hasItem):
(WebCore::JSDOMApplicationCache::add):
(WebCore::JSDOMApplicationCache::remove):

  • bindings/js/JSDOMFormDataCustom.cpp:

(WebCore::JSDOMFormData::append):

  • bindings/js/JSDOMWindowCustom.cpp:

(WebCore::JSDOMWindow::open):
(WebCore::JSDOMWindow::showModalDialog):
(WebCore::JSDOMWindow::postMessage):
(WebCore::JSDOMWindow::setTimeout):
(WebCore::JSDOMWindow::setInterval):
(WebCore::JSDOMWindow::addEventListener):
(WebCore::JSDOMWindow::removeEventListener):
(WebCore::JSDOMWindow::openDatabase):

  • bindings/js/JSDatabaseCustom.cpp:

(WebCore::JSDatabase::changeVersion):
(WebCore::createTransaction):
(WebCore::JSDatabase::transaction):
(WebCore::JSDatabase::readTransaction):

  • bindings/js/JSDatabaseSyncCustom.cpp:

(WebCore::JSDatabaseSync::changeVersion):
(WebCore::createTransaction):
(WebCore::JSDatabaseSync::transaction):
(WebCore::JSDatabaseSync::readTransaction):

  • bindings/js/JSDedicatedWorkerContextCustom.cpp:

(WebCore::JSDedicatedWorkerContext::postMessage):

  • bindings/js/JSDesktopNotificationsCustom.cpp:

(WebCore::JSNotificationCenter::requestPermission):

  • bindings/js/JSFloatArrayCustom.cpp:

(WebCore::JSFloatArray::set):

  • bindings/js/JSGeolocationCustom.cpp:

(WebCore::JSGeolocation::getCurrentPosition):
(WebCore::JSGeolocation::watchPosition):

  • bindings/js/JSHTMLAllCollectionCustom.cpp:

(WebCore::callHTMLAllCollection):
(WebCore::JSHTMLAllCollection::item):
(WebCore::JSHTMLAllCollection::namedItem):

  • bindings/js/JSHTMLCanvasElementCustom.cpp:

(WebCore::JSHTMLCanvasElement::getContext):

  • bindings/js/JSHTMLCollectionCustom.cpp:

(WebCore::callHTMLCollection):
(WebCore::JSHTMLCollection::item):
(WebCore::JSHTMLCollection::namedItem):

  • bindings/js/JSHTMLDocumentCustom.cpp:

(WebCore::JSHTMLDocument::open):
(WebCore::documentWrite):
(WebCore::JSHTMLDocument::write):
(WebCore::JSHTMLDocument::writeln):

  • bindings/js/JSHTMLInputElementCustom.cpp:

(WebCore::JSHTMLInputElement::setSelectionRange):

  • bindings/js/JSHTMLOptionsCollectionCustom.cpp:

(WebCore::JSHTMLOptionsCollection::add):
(WebCore::JSHTMLOptionsCollection::remove):

  • bindings/js/JSHTMLSelectElementCustom.cpp:

(WebCore::JSHTMLSelectElement::remove):

  • bindings/js/JSHistoryCustom.cpp:

(WebCore::JSHistory::pushState):
(WebCore::JSHistory::replaceState):

  • bindings/js/JSInjectedScriptHostCustom.cpp:

(WebCore::JSInjectedScriptHost::databaseForId):
(WebCore::JSInjectedScriptHost::currentCallFrame):
(WebCore::JSInjectedScriptHost::nodeForId):
(WebCore::JSInjectedScriptHost::pushNodePathToFrontend):
(WebCore::JSInjectedScriptHost::selectDatabase):
(WebCore::JSInjectedScriptHost::selectDOMStorage):
(WebCore::JSInjectedScriptHost::reportDidDispatchOnInjectedScript):

  • bindings/js/JSInspectorFrontendHostCustom.cpp:

(WebCore::JSInspectorFrontendHost::platform):
(WebCore::JSInspectorFrontendHost::port):
(WebCore::JSInspectorFrontendHost::showContextMenu):

  • bindings/js/JSInt16ArrayCustom.cpp:

(WebCore::JSInt16Array::set):

  • bindings/js/JSInt32ArrayCustom.cpp:

(WebCore::JSInt32Array::set):

  • bindings/js/JSInt8ArrayCustom.cpp:

(WebCore::JSInt8Array::set):

  • bindings/js/JSJavaScriptCallFrameCustom.cpp:

(WebCore::JSJavaScriptCallFrame::evaluate):
(WebCore::JSJavaScriptCallFrame::scopeType):

  • bindings/js/JSLocationCustom.cpp:

(WebCore::JSLocation::replace):
(WebCore::JSLocation::reload):
(WebCore::JSLocation::assign):
(WebCore::JSLocation::toString):

  • bindings/js/JSMessageEventCustom.cpp:

(WebCore::JSMessageEvent::initMessageEvent):

  • bindings/js/JSMessagePortCustom.cpp:

(WebCore::JSMessagePort::postMessage):

  • bindings/js/JSMessagePortCustom.h:

(WebCore::handlePostMessage):

  • bindings/js/JSNodeCustom.cpp:

(WebCore::JSNode::insertBefore):
(WebCore::JSNode::replaceChild):
(WebCore::JSNode::removeChild):
(WebCore::JSNode::appendChild):

  • bindings/js/JSNodeListCustom.cpp:

(WebCore::callNodeList):

  • bindings/js/JSPluginElementFunctions.cpp:

(WebCore::callPlugin):

  • bindings/js/JSSQLResultSetRowListCustom.cpp:

(WebCore::JSSQLResultSetRowList::item):

  • bindings/js/JSSQLTransactionCustom.cpp:

(WebCore::JSSQLTransaction::executeSql):

  • bindings/js/JSSQLTransactionSyncCustom.cpp:

(WebCore::JSSQLTransactionSync::executeSql):

  • bindings/js/JSSVGLengthCustom.cpp:

(WebCore::JSSVGLength::convertToSpecifiedUnits):

  • bindings/js/JSSVGMatrixCustom.cpp:

(WebCore::JSSVGMatrix::multiply):
(WebCore::JSSVGMatrix::inverse):
(WebCore::JSSVGMatrix::rotateFromVector):

  • bindings/js/JSSVGPODListCustom.h:

(WebCore::JSSVGPODListCustom::clear):
(WebCore::JSSVGPODListCustom::initialize):
(WebCore::JSSVGPODListCustom::getItem):
(WebCore::JSSVGPODListCustom::insertItemBefore):
(WebCore::JSSVGPODListCustom::replaceItem):
(WebCore::JSSVGPODListCustom::removeItem):
(WebCore::JSSVGPODListCustom::appendItem):

  • bindings/js/JSSVGPathSegListCustom.cpp:

(WebCore::JSSVGPathSegList::clear):
(WebCore::JSSVGPathSegList::initialize):
(WebCore::JSSVGPathSegList::getItem):
(WebCore::JSSVGPathSegList::insertItemBefore):
(WebCore::JSSVGPathSegList::replaceItem):
(WebCore::JSSVGPathSegList::removeItem):
(WebCore::JSSVGPathSegList::appendItem):

  • bindings/js/JSUint16ArrayCustom.cpp:

(WebCore::JSUint16Array::set):

  • bindings/js/JSUint32ArrayCustom.cpp:

(WebCore::JSUint32Array::set):

  • bindings/js/JSUint8ArrayCustom.cpp:

(WebCore::JSUint8Array::set):

  • bindings/js/JSWebGLRenderingContextCustom.cpp:

(WebCore::JSWebGLRenderingContext::bufferData):
(WebCore::JSWebGLRenderingContext::bufferSubData):
(WebCore::getObjectParameter):
(WebCore::JSWebGLRenderingContext::getBufferParameter):
(WebCore::JSWebGLRenderingContext::getFramebufferAttachmentParameter):
(WebCore::JSWebGLRenderingContext::getParameter):
(WebCore::JSWebGLRenderingContext::getProgramParameter):
(WebCore::JSWebGLRenderingContext::getRenderbufferParameter):
(WebCore::JSWebGLRenderingContext::getShaderParameter):
(WebCore::JSWebGLRenderingContext::getTexParameter):
(WebCore::JSWebGLRenderingContext::getUniform):
(WebCore::JSWebGLRenderingContext::getVertexAttrib):
(WebCore::JSWebGLRenderingContext::texImage2D):
(WebCore::JSWebGLRenderingContext::texSubImage2D):
(WebCore::dataFunctionf):
(WebCore::dataFunctioni):
(WebCore::dataFunctionMatrix):
(WebCore::JSWebGLRenderingContext::uniform1fv):
(WebCore::JSWebGLRenderingContext::uniform1iv):
(WebCore::JSWebGLRenderingContext::uniform2fv):
(WebCore::JSWebGLRenderingContext::uniform2iv):
(WebCore::JSWebGLRenderingContext::uniform3fv):
(WebCore::JSWebGLRenderingContext::uniform3iv):
(WebCore::JSWebGLRenderingContext::uniform4fv):
(WebCore::JSWebGLRenderingContext::uniform4iv):
(WebCore::JSWebGLRenderingContext::uniformMatrix2fv):
(WebCore::JSWebGLRenderingContext::uniformMatrix3fv):
(WebCore::JSWebGLRenderingContext::uniformMatrix4fv):
(WebCore::JSWebGLRenderingContext::vertexAttrib1fv):
(WebCore::JSWebGLRenderingContext::vertexAttrib2fv):
(WebCore::JSWebGLRenderingContext::vertexAttrib3fv):
(WebCore::JSWebGLRenderingContext::vertexAttrib4fv):

  • bindings/js/JSWebSocketCustom.cpp:

(WebCore::JSWebSocket::send):

  • bindings/js/JSWorkerContextCustom.cpp:

(WebCore::JSWorkerContext::importScripts):
(WebCore::JSWorkerContext::setTimeout):
(WebCore::JSWorkerContext::setInterval):
(WebCore::JSWorkerContext::openDatabase):
(WebCore::JSWorkerContext::openDatabaseSync):

  • bindings/js/JSWorkerCustom.cpp:

(WebCore::JSWorker::postMessage):

  • bindings/js/JSXMLHttpRequestCustom.cpp:

(WebCore::JSXMLHttpRequest::open):
(WebCore::JSXMLHttpRequest::send):

  • bindings/js/JSXSLTProcessorCustom.cpp:

(WebCore::JSXSLTProcessor::importStylesheet):
(WebCore::JSXSLTProcessor::transformToFragment):
(WebCore::JSXSLTProcessor::transformToDocument):
(WebCore::JSXSLTProcessor::setParameter):
(WebCore::JSXSLTProcessor::getParameter):
(WebCore::JSXSLTProcessor::removeParameter):

  • bindings/js/ScheduledAction.cpp:

(WebCore::ScheduledAction::create):
(WebCore::ScheduledAction::ScheduledAction):

  • bindings/js/ScheduledAction.h:
  • bindings/js/ScriptCallFrame.cpp:

(WebCore::ScriptCallFrame::ScriptCallFrame):

  • bindings/js/ScriptCallFrame.h:
  • bindings/js/ScriptCallStack.cpp:

(WebCore::ScriptCallStack::ScriptCallStack):
(WebCore::ScriptCallStack::initialize):

  • bindings/js/ScriptCallStack.h:
  • bindings/scripts/CodeGeneratorJS.pm:
  • bridge/c/c_instance.cpp:

(JSC::Bindings::CInstance::invokeMethod):
(JSC::Bindings::CInstance::invokeDefaultMethod):

  • bridge/c/c_instance.h:
  • bridge/jni/jsc/JavaInstanceJSC.cpp:

(JavaInstance::invokeMethod):

  • bridge/jni/jsc/JavaInstanceJSC.h:
  • bridge/jsc/BridgeJSC.h:

(JSC::Bindings::Instance::invokeDefaultMethod):

  • bridge/objc/objc_instance.h:
  • bridge/objc/objc_instance.mm:

(ObjcInstance::invokeMethod):
(ObjcInstance::invokeObjcMethod):
(ObjcInstance::invokeDefaultMethod):

  • bridge/objc/objc_runtime.mm:

(JSC::Bindings::callObjCFallbackObject):

  • bridge/runtime_method.cpp:

(JSC::callRuntimeMethod):

  • bridge/runtime_object.cpp:

(JSC::Bindings::callRuntimeObject):

WebKit/mac: Simplified the host calling convention.

Reviewed by Sam Weinig, Gavin Barraclough, Oliver Hunt.

PART ONE: Functional code changes.

[ None in WebKit ]

PART TWO: Global search and replace.

In the areas below, I used global search-and-replace to change

(ExecState*, JSObject*, JSValue, const ArgList&) => (ExecState*)
args.size() => exec->argumentCount()
args.at(i) => exec->argument(i)

  • Plugins/Hosted/ProxyInstance.h:
  • Plugins/Hosted/ProxyInstance.mm:

(WebKit::ProxyInstance::invoke):
(WebKit::ProxyInstance::invokeMethod):
(WebKit::ProxyInstance::invokeDefaultMethod):

LayoutTests: Simplified the host calling convention.

Reviewed by Sam Weinig, Gavin Barraclough, Oliver Hunt.

Changed these results to expect to fail to stringify their exception
objects in the case of stack overflow. (Standardizing the calling
convention has implicitly added stack overflow checks to some places
where they used to be missing.)

In a future patch, I plan to implement a more reliable way to stringify
exceptions without invoking a JS function. For now, though, it seems best
to match other test results, instead of silently overflowing the stack.

  • fast/js/global-recursion-on-full-stack-expected.txt:
  • fast/xmlhttprequest/xmlhttprequest-recursive-sync-event-expected.txt:
  • Property svn:eol-style set to native
File size: 15.9 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2002, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22#ifndef Operations_h
23#define Operations_h
24
25#include "ExceptionHelpers.h"
26#include "Interpreter.h"
27#include "JSImmediate.h"
28#include "JSNumberCell.h"
29#include "JSString.h"
30
31namespace JSC {
32
33 NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue);
34 JSValue jsTypeStringForValue(CallFrame*, JSValue);
35 bool jsIsObjectType(JSValue);
36 bool jsIsFunctionType(JSValue);
37
38 ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2)
39 {
40 unsigned length1 = s1->length();
41 if (!length1)
42 return s2;
43 unsigned length2 = s2->length();
44 if (!length2)
45 return s1;
46 if ((length1 + length2) < length1)
47 return throwOutOfMemoryError(exec);
48
49 unsigned fiberCount = s1->size() + s2->size();
50 JSGlobalData* globalData = &exec->globalData();
51
52 if (fiberCount <= JSString::s_maxInternalRopeLength)
53 return new (globalData) JSString(globalData, fiberCount, s1, s2);
54
55 JSString::RopeBuilder ropeBuilder(fiberCount);
56 if (UNLIKELY(ropeBuilder.isOutOfMemory()))
57 return throwOutOfMemoryError(exec);
58 ropeBuilder.append(s1);
59 ropeBuilder.append(s2);
60 return new (globalData) JSString(globalData, ropeBuilder.release());
61 }
62
63 ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, JSString* s2)
64 {
65 unsigned length1 = u1.size();
66 if (!length1)
67 return s2;
68 unsigned length2 = s2->length();
69 if (!length2)
70 return jsString(exec, u1);
71 if ((length1 + length2) < length1)
72 return throwOutOfMemoryError(exec);
73
74 unsigned fiberCount = 1 + s2->size();
75 JSGlobalData* globalData = &exec->globalData();
76
77 if (fiberCount <= JSString::s_maxInternalRopeLength)
78 return new (globalData) JSString(globalData, fiberCount, u1, s2);
79
80 JSString::RopeBuilder ropeBuilder(fiberCount);
81 if (UNLIKELY(ropeBuilder.isOutOfMemory()))
82 return throwOutOfMemoryError(exec);
83 ropeBuilder.append(u1);
84 ropeBuilder.append(s2);
85 return new (globalData) JSString(globalData, ropeBuilder.release());
86 }
87
88 ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, const UString& u2)
89 {
90 unsigned length1 = s1->length();
91 if (!length1)
92 return jsString(exec, u2);
93 unsigned length2 = u2.size();
94 if (!length2)
95 return s1;
96 if ((length1 + length2) < length1)
97 return throwOutOfMemoryError(exec);
98
99 unsigned fiberCount = s1->size() + 1;
100 JSGlobalData* globalData = &exec->globalData();
101
102 if (fiberCount <= JSString::s_maxInternalRopeLength)
103 return new (globalData) JSString(globalData, fiberCount, s1, u2);
104
105 JSString::RopeBuilder ropeBuilder(fiberCount);
106 if (UNLIKELY(ropeBuilder.isOutOfMemory()))
107 return throwOutOfMemoryError(exec);
108 ropeBuilder.append(s1);
109 ropeBuilder.append(u2);
110 return new (globalData) JSString(globalData, ropeBuilder.release());
111 }
112
113 ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, const UString& u2)
114 {
115 unsigned length1 = u1.size();
116 if (!length1)
117 return jsString(exec, u2);
118 unsigned length2 = u2.size();
119 if (!length2)
120 return jsString(exec, u1);
121 if ((length1 + length2) < length1)
122 return throwOutOfMemoryError(exec);
123
124 JSGlobalData* globalData = &exec->globalData();
125 return new (globalData) JSString(globalData, u1, u2);
126 }
127
128 ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, const UString& u2, const UString& u3)
129 {
130 unsigned length1 = u1.size();
131 unsigned length2 = u2.size();
132 unsigned length3 = u3.size();
133 if (!length1)
134 return jsString(exec, u2, u3);
135 if (!length2)
136 return jsString(exec, u1, u3);
137 if (!length3)
138 return jsString(exec, u1, u2);
139
140 if ((length1 + length2) < length1)
141 return throwOutOfMemoryError(exec);
142 if ((length1 + length2 + length3) < length3)
143 return throwOutOfMemoryError(exec);
144
145 JSGlobalData* globalData = &exec->globalData();
146 return new (globalData) JSString(globalData, u1, u2, u3);
147 }
148
149 ALWAYS_INLINE JSValue jsString(ExecState* exec, Register* strings, unsigned count)
150 {
151 ASSERT(count >= 3);
152
153 unsigned fiberCount = 0;
154 for (unsigned i = 0; i < count; ++i) {
155 JSValue v = strings[i].jsValue();
156 if (LIKELY(v.isString()))
157 fiberCount += asString(v)->size();
158 else
159 ++fiberCount;
160 }
161
162 JSGlobalData* globalData = &exec->globalData();
163 if (fiberCount == 3)
164 return new (globalData) JSString(exec, strings[0].jsValue(), strings[1].jsValue(), strings[2].jsValue());
165
166 JSString::RopeBuilder ropeBuilder(fiberCount);
167 if (UNLIKELY(ropeBuilder.isOutOfMemory()))
168 return throwOutOfMemoryError(exec);
169
170 unsigned length = 0;
171 bool overflow = false;
172
173 for (unsigned i = 0; i < count; ++i) {
174 JSValue v = strings[i].jsValue();
175 if (LIKELY(v.isString()))
176 ropeBuilder.append(asString(v));
177 else
178 ropeBuilder.append(v.toString(exec));
179
180 unsigned newLength = ropeBuilder.length();
181 if (newLength < length)
182 overflow = true;
183 length = newLength;
184 }
185
186 if (overflow)
187 return throwOutOfMemoryError(exec);
188
189 return new (globalData) JSString(globalData, ropeBuilder.release());
190 }
191
192 ALWAYS_INLINE JSValue jsString(ExecState* exec, JSValue thisValue)
193 {
194 unsigned fiberCount = 0;
195 if (LIKELY(thisValue.isString()))
196 fiberCount += asString(thisValue)->size();
197 else
198 ++fiberCount;
199 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
200 JSValue v = exec->argument(i);
201 if (LIKELY(v.isString()))
202 fiberCount += asString(v)->size();
203 else
204 ++fiberCount;
205 }
206
207 JSString::RopeBuilder ropeBuilder(fiberCount);
208 if (UNLIKELY(ropeBuilder.isOutOfMemory()))
209 return throwOutOfMemoryError(exec);
210
211 if (LIKELY(thisValue.isString()))
212 ropeBuilder.append(asString(thisValue));
213 else
214 ropeBuilder.append(thisValue.toString(exec));
215
216 unsigned length = 0;
217 bool overflow = false;
218
219 for (unsigned i = 0; i < exec->argumentCount(); ++i) {
220 JSValue v = exec->argument(i);
221 if (LIKELY(v.isString()))
222 ropeBuilder.append(asString(v));
223 else
224 ropeBuilder.append(v.toString(exec));
225
226 unsigned newLength = ropeBuilder.length();
227 if (newLength < length)
228 overflow = true;
229 length = newLength;
230 }
231
232 if (overflow)
233 return throwOutOfMemoryError(exec);
234
235 JSGlobalData* globalData = &exec->globalData();
236 return new (globalData) JSString(globalData, ropeBuilder.release());
237 }
238
239 // ECMA 11.9.3
240 inline bool JSValue::equal(ExecState* exec, JSValue v1, JSValue v2)
241 {
242 if (v1.isInt32() && v2.isInt32())
243 return v1 == v2;
244
245 return equalSlowCase(exec, v1, v2);
246 }
247
248 ALWAYS_INLINE bool JSValue::equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2)
249 {
250 do {
251 if (v1.isNumber() && v2.isNumber())
252 return v1.uncheckedGetNumber() == v2.uncheckedGetNumber();
253
254 bool s1 = v1.isString();
255 bool s2 = v2.isString();
256 if (s1 && s2)
257 return asString(v1)->value(exec) == asString(v2)->value(exec);
258
259 if (v1.isUndefinedOrNull()) {
260 if (v2.isUndefinedOrNull())
261 return true;
262 if (!v2.isCell())
263 return false;
264 return v2.asCell()->structure()->typeInfo().masqueradesAsUndefined();
265 }
266
267 if (v2.isUndefinedOrNull()) {
268 if (!v1.isCell())
269 return false;
270 return v1.asCell()->structure()->typeInfo().masqueradesAsUndefined();
271 }
272
273 if (v1.isObject()) {
274 if (v2.isObject())
275 return v1 == v2;
276 JSValue p1 = v1.toPrimitive(exec);
277 if (exec->hadException())
278 return false;
279 v1 = p1;
280 if (v1.isInt32() && v2.isInt32())
281 return v1 == v2;
282 continue;
283 }
284
285 if (v2.isObject()) {
286 JSValue p2 = v2.toPrimitive(exec);
287 if (exec->hadException())
288 return false;
289 v2 = p2;
290 if (v1.isInt32() && v2.isInt32())
291 return v1 == v2;
292 continue;
293 }
294
295 if (s1 || s2) {
296 double d1 = v1.toNumber(exec);
297 double d2 = v2.toNumber(exec);
298 return d1 == d2;
299 }
300
301 if (v1.isBoolean()) {
302 if (v2.isNumber())
303 return static_cast<double>(v1.getBoolean()) == v2.uncheckedGetNumber();
304 } else if (v2.isBoolean()) {
305 if (v1.isNumber())
306 return v1.uncheckedGetNumber() == static_cast<double>(v2.getBoolean());
307 }
308
309 return v1 == v2;
310 } while (true);
311 }
312
313 // ECMA 11.9.3
314 ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2)
315 {
316 ASSERT(v1.isCell() && v2.isCell());
317
318 if (v1.asCell()->isString() && v2.asCell()->isString())
319 return asString(v1)->value(exec) == asString(v2)->value(exec);
320
321 return v1 == v2;
322 }
323
324 inline bool JSValue::strictEqual(ExecState* exec, JSValue v1, JSValue v2)
325 {
326 if (v1.isInt32() && v2.isInt32())
327 return v1 == v2;
328
329 if (v1.isNumber() && v2.isNumber())
330 return v1.uncheckedGetNumber() == v2.uncheckedGetNumber();
331
332 if (!v1.isCell() || !v2.isCell())
333 return v1 == v2;
334
335 return strictEqualSlowCaseInline(exec, v1, v2);
336 }
337
338 ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2)
339 {
340 if (v1.isInt32() && v2.isInt32())
341 return v1.asInt32() < v2.asInt32();
342
343 double n1;
344 double n2;
345 if (v1.getNumber(n1) && v2.getNumber(n2))
346 return n1 < n2;
347
348 JSGlobalData* globalData = &callFrame->globalData();
349 if (isJSString(globalData, v1) && isJSString(globalData, v2))
350 return asString(v1)->value(callFrame) < asString(v2)->value(callFrame);
351
352 JSValue p1;
353 JSValue p2;
354 bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
355 bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
356
357 if (wasNotString1 | wasNotString2)
358 return n1 < n2;
359
360 return asString(p1)->value(callFrame) < asString(p2)->value(callFrame);
361 }
362
363 inline bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2)
364 {
365 if (v1.isInt32() && v2.isInt32())
366 return v1.asInt32() <= v2.asInt32();
367
368 double n1;
369 double n2;
370 if (v1.getNumber(n1) && v2.getNumber(n2))
371 return n1 <= n2;
372
373 JSGlobalData* globalData = &callFrame->globalData();
374 if (isJSString(globalData, v1) && isJSString(globalData, v2))
375 return !(asString(v2)->value(callFrame) < asString(v1)->value(callFrame));
376
377 JSValue p1;
378 JSValue p2;
379 bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
380 bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
381
382 if (wasNotString1 | wasNotString2)
383 return n1 <= n2;
384
385 return !(asString(p2)->value(callFrame) < asString(p1)->value(callFrame));
386 }
387
388 // Fast-path choices here are based on frequency data from SunSpider:
389 // <times> Add case: <t1> <t2>
390 // ---------------------------
391 // 5626160 Add case: 3 3 (of these, 3637690 are for immediate values)
392 // 247412 Add case: 5 5
393 // 20900 Add case: 5 6
394 // 13962 Add case: 5 3
395 // 4000 Add case: 3 5
396
397 ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2)
398 {
399 double left = 0.0, right;
400 if (v1.getNumber(left) && v2.getNumber(right))
401 return jsNumber(callFrame, left + right);
402
403 if (v1.isString()) {
404 return v2.isString()
405 ? jsString(callFrame, asString(v1), asString(v2))
406 : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame));
407 }
408
409 // All other cases are pretty uncommon
410 return jsAddSlowCase(callFrame, v1, v2);
411 }
412
413 inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase, const Identifier& propertyName, size_t& slotOffset)
414 {
415 JSCell* cell = asCell(base);
416 size_t count = 0;
417
418 while (slotBase != cell) {
419 JSValue v = cell->structure()->prototypeForLookup(callFrame);
420
421 // If we didn't find slotBase in base's prototype chain, then base
422 // must be a proxy for another object.
423
424 if (v.isNull())
425 return 0;
426
427 cell = asCell(v);
428
429 // Since we're accessing a prototype in a loop, it's a good bet that it
430 // should not be treated as a dictionary.
431 if (cell->structure()->isDictionary()) {
432 asObject(cell)->flattenDictionaryObject();
433 if (slotBase == cell)
434 slotOffset = cell->structure()->get(propertyName);
435 }
436
437 ++count;
438 }
439
440 ASSERT(count);
441 return count;
442 }
443
444 inline size_t normalizePrototypeChain(CallFrame* callFrame, JSCell* base)
445 {
446 size_t count = 0;
447 while (1) {
448 JSValue v = base->structure()->prototypeForLookup(callFrame);
449 if (v.isNull())
450 return count;
451
452 base = asCell(v);
453
454 // Since we're accessing a prototype in a loop, it's a good bet that it
455 // should not be treated as a dictionary.
456 if (base->structure()->isDictionary())
457 asObject(base)->flattenDictionaryObject();
458
459 ++count;
460 }
461 }
462
463 ALWAYS_INLINE JSValue resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain)
464 {
465 ScopeChainIterator iter = scopeChain->begin();
466 ScopeChainIterator next = iter;
467 ++next;
468 ScopeChainIterator end = scopeChain->end();
469 ASSERT(iter != end);
470
471 PropertySlot slot;
472 JSObject* base;
473 while (true) {
474 base = *iter;
475 if (next == end || base->getPropertySlot(callFrame, property, slot))
476 return base;
477
478 iter = next;
479 ++next;
480 }
481
482 ASSERT_NOT_REACHED();
483 return JSValue();
484 }
485} // namespace JSC
486
487#endif // Operations_h
Note: See TracBrowser for help on using the repository browser.