source: webkit/trunk/JavaScriptCore/VM/Machine.cpp@ 36263

Last change on this file since 36263 was 36263, checked in by [email protected], 17 years ago

2008-09-07 Cameron Zwarich <[email protected]>

Reviewed by Maciej Stachowiak.

Bug 20704: Replace the KJS namespace
<https://bugs.webkit.org/show_bug.cgi?id=20704>

Rename the KJS namespace to JSC. There are still some uses of KJS in
preprocessor macros and comments, but these will also be changed some
time in the near future. There are also some uses in the names of JNI
functions, but I will check if these are safe to change as well.

JavaScriptCore:

  • API/APICast.h: (toJS): (toRef): (toGlobalRef):
  • API/JSBase.cpp:
  • API/JSCallbackConstructor.cpp:
  • API/JSCallbackConstructor.h:
  • API/JSCallbackFunction.cpp:
  • API/JSCallbackFunction.h:
  • API/JSCallbackObject.cpp:
  • API/JSCallbackObject.h:
  • API/JSCallbackObjectFunctions.h:
  • API/JSClassRef.cpp: (OpaqueJSClass::staticValues): (OpaqueJSClass::staticFunctions):
  • API/JSClassRef.h:
  • API/JSContextRef.cpp:
  • API/JSObjectRef.cpp:
  • API/JSProfilerPrivate.cpp:
  • API/JSStringRef.cpp:
  • API/JSValueRef.cpp: (JSValueGetType):
  • API/OpaqueJSString.cpp:
  • API/OpaqueJSString.h:
  • JavaScriptCore.Debug.exp:
  • JavaScriptCore.base.exp:
  • VM/CTI.cpp: (JSC::):
  • VM/CTI.h:
  • VM/CodeBlock.cpp:
  • VM/CodeBlock.h:
  • VM/CodeGenerator.cpp:
  • VM/CodeGenerator.h:
  • VM/ExceptionHelpers.cpp:
  • VM/ExceptionHelpers.h:
  • VM/Instruction.h:
  • VM/JSPropertyNameIterator.cpp:
  • VM/JSPropertyNameIterator.h:
  • VM/LabelID.h:
  • VM/Machine.cpp:
  • VM/Machine.h:
  • VM/Opcode.cpp:
  • VM/Opcode.h:
  • VM/Register.h: (WTF::):
  • VM/RegisterFile.cpp:
  • VM/RegisterFile.h:
  • VM/RegisterID.h: (WTF::):
  • VM/SamplingTool.cpp:
  • VM/SamplingTool.h:
  • VM/SegmentedVector.h:
  • kjs/ArgList.cpp:
  • kjs/ArgList.h:
  • kjs/Arguments.cpp:
  • kjs/Arguments.h:
  • kjs/ArrayConstructor.cpp:
  • kjs/ArrayConstructor.h:
  • kjs/ArrayPrototype.cpp:
  • kjs/ArrayPrototype.h:
  • kjs/BatchedTransitionOptimizer.h:
  • kjs/BooleanConstructor.cpp:
  • kjs/BooleanConstructor.h:
  • kjs/BooleanObject.cpp:
  • kjs/BooleanObject.h:
  • kjs/BooleanPrototype.cpp:
  • kjs/BooleanPrototype.h:
  • kjs/CallData.cpp:
  • kjs/CallData.h:
  • kjs/ClassInfo.h:
  • kjs/CommonIdentifiers.cpp:
  • kjs/CommonIdentifiers.h:
  • kjs/ConstructData.cpp:
  • kjs/ConstructData.h:
  • kjs/DateConstructor.cpp:
  • kjs/DateConstructor.h:
  • kjs/DateInstance.cpp: (JSC::DateInstance::msToGregorianDateTime):
  • kjs/DateInstance.h:
  • kjs/DateMath.cpp:
  • kjs/DateMath.h:
  • kjs/DatePrototype.cpp:
  • kjs/DatePrototype.h:
  • kjs/DebuggerCallFrame.cpp:
  • kjs/DebuggerCallFrame.h:
  • kjs/Error.cpp:
  • kjs/Error.h:
  • kjs/ErrorConstructor.cpp:
  • kjs/ErrorConstructor.h:
  • kjs/ErrorInstance.cpp:
  • kjs/ErrorInstance.h:
  • kjs/ErrorPrototype.cpp:
  • kjs/ErrorPrototype.h:
  • kjs/ExecState.cpp:
  • kjs/ExecState.h:
  • kjs/FunctionConstructor.cpp:
  • kjs/FunctionConstructor.h:
  • kjs/FunctionPrototype.cpp:
  • kjs/FunctionPrototype.h:
  • kjs/GetterSetter.cpp:
  • kjs/GetterSetter.h:
  • kjs/GlobalEvalFunction.cpp:
  • kjs/GlobalEvalFunction.h:
  • kjs/IndexToNameMap.cpp:
  • kjs/IndexToNameMap.h:
  • kjs/InitializeThreading.cpp:
  • kjs/InitializeThreading.h:
  • kjs/InternalFunction.cpp:
  • kjs/InternalFunction.h: (JSC::InternalFunction::InternalFunction):
  • kjs/JSActivation.cpp:
  • kjs/JSActivation.h:
  • kjs/JSArray.cpp:
  • kjs/JSArray.h:
  • kjs/JSCell.cpp:
  • kjs/JSCell.h:
  • kjs/JSFunction.cpp:
  • kjs/JSFunction.h: (JSC::JSFunction::JSFunction):
  • kjs/JSGlobalData.cpp: (JSC::JSGlobalData::JSGlobalData):
  • kjs/JSGlobalData.h:
  • kjs/JSGlobalObject.cpp:
  • kjs/JSGlobalObject.h:
  • kjs/JSGlobalObjectFunctions.cpp:
  • kjs/JSGlobalObjectFunctions.h:
  • kjs/JSImmediate.cpp:
  • kjs/JSImmediate.h:
  • kjs/JSLock.cpp:
  • kjs/JSLock.h:
  • kjs/JSNotAnObject.cpp:
  • kjs/JSNotAnObject.h:
  • kjs/JSNumberCell.cpp:
  • kjs/JSNumberCell.h:
  • kjs/JSObject.cpp:
  • kjs/JSObject.h:
  • kjs/JSStaticScopeObject.cpp:
  • kjs/JSStaticScopeObject.h:
  • kjs/JSString.cpp:
  • kjs/JSString.h:
  • kjs/JSType.h:
  • kjs/JSValue.cpp:
  • kjs/JSValue.h:
  • kjs/JSVariableObject.cpp:
  • kjs/JSVariableObject.h:
  • kjs/JSWrapperObject.cpp:
  • kjs/JSWrapperObject.h:
  • kjs/LabelStack.cpp:
  • kjs/LabelStack.h:
  • kjs/MathObject.cpp:
  • kjs/MathObject.h:
  • kjs/NativeErrorConstructor.cpp:
  • kjs/NativeErrorConstructor.h:
  • kjs/NativeErrorPrototype.cpp:
  • kjs/NativeErrorPrototype.h:
  • kjs/NodeInfo.h:
  • kjs/NumberConstructor.cpp:
  • kjs/NumberConstructor.h:
  • kjs/NumberObject.cpp:
  • kjs/NumberObject.h:
  • kjs/NumberPrototype.cpp:
  • kjs/NumberPrototype.h:
  • kjs/ObjectConstructor.cpp:
  • kjs/ObjectConstructor.h:
  • kjs/ObjectPrototype.cpp:
  • kjs/ObjectPrototype.h:
  • kjs/Parser.cpp:
  • kjs/Parser.h:
  • kjs/PropertyMap.cpp: (JSC::PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger):
  • kjs/PropertyMap.h:
  • kjs/PropertyNameArray.cpp:
  • kjs/PropertyNameArray.h:
  • kjs/PropertySlot.cpp:
  • kjs/PropertySlot.h:
  • kjs/PrototypeFunction.cpp:
  • kjs/PrototypeFunction.h:
  • kjs/PutPropertySlot.h:
  • kjs/RegExpConstructor.cpp:
  • kjs/RegExpConstructor.h:
  • kjs/RegExpObject.cpp:
  • kjs/RegExpObject.h:
  • kjs/RegExpPrototype.cpp:
  • kjs/RegExpPrototype.h:
  • kjs/ScopeChain.cpp:
  • kjs/ScopeChain.h:
  • kjs/ScopeChainMark.h:
  • kjs/Shell.cpp: (jscmain):
  • kjs/SmallStrings.cpp:
  • kjs/SmallStrings.h:
  • kjs/SourceProvider.h:
  • kjs/SourceRange.h:
  • kjs/StringConstructor.cpp:
  • kjs/StringConstructor.h:
  • kjs/StringObject.cpp:
  • kjs/StringObject.h:
  • kjs/StringObjectThatMasqueradesAsUndefined.h:
  • kjs/StringPrototype.cpp:
  • kjs/StringPrototype.h:
  • kjs/StructureID.cpp:
  • kjs/StructureID.h:
  • kjs/SymbolTable.h:
  • kjs/collector.cpp:
  • kjs/collector.h:
  • kjs/completion.h:
  • kjs/create_hash_table:
  • kjs/debugger.cpp:
  • kjs/debugger.h:
  • kjs/dtoa.cpp:
  • kjs/dtoa.h:
  • kjs/grammar.y:
  • kjs/identifier.cpp:
  • kjs/identifier.h: (JSC::Identifier::equal):
  • kjs/interpreter.cpp:
  • kjs/interpreter.h:
  • kjs/lexer.cpp: (JSC::Lexer::Lexer): (JSC::Lexer::clear): (JSC::Lexer::makeIdentifier):
  • kjs/lexer.h:
  • kjs/lookup.cpp:
  • kjs/lookup.h:
  • kjs/nodes.cpp:
  • kjs/nodes.h:
  • kjs/nodes2string.cpp:
  • kjs/operations.cpp:
  • kjs/operations.h:
  • kjs/protect.h:
  • kjs/regexp.cpp:
  • kjs/regexp.h:
  • kjs/ustring.cpp:
  • kjs/ustring.h: (JSC::operator!=): (JSC::IdentifierRepHash::hash): (WTF::):
  • masm/MacroAssembler.h:
  • masm/MacroAssemblerWin.cpp:
  • masm/X86Assembler.h:
  • pcre/pcre_exec.cpp:
  • profiler/CallIdentifier.h: (WTF::):
  • profiler/HeavyProfile.cpp:
  • profiler/HeavyProfile.h:
  • profiler/Profile.cpp:
  • profiler/Profile.h:
  • profiler/ProfileGenerator.cpp:
  • profiler/ProfileGenerator.h:
  • profiler/ProfileNode.cpp:
  • profiler/ProfileNode.h:
  • profiler/Profiler.cpp:
  • profiler/Profiler.h:
  • profiler/TreeProfile.cpp:
  • profiler/TreeProfile.h:
  • wrec/WREC.cpp:
  • wrec/WREC.h:
  • wtf/AVLTree.h:

WebCore:

  • WebCore.base.exp:
  • bindings/js/GCController.cpp:
  • bindings/js/JSAttrCustom.cpp:
  • bindings/js/JSAudioConstructor.cpp:
  • bindings/js/JSAudioConstructor.h: (WebCore::JSAudioConstructor::classInfo):
  • bindings/js/JSCSSRuleCustom.cpp:
  • bindings/js/JSCSSStyleDeclarationCustom.cpp:
  • bindings/js/JSCSSValueCustom.cpp:
  • bindings/js/JSCanvasPixelArrayCustom.cpp:
  • bindings/js/JSCanvasRenderingContext2DCustom.cpp:
  • bindings/js/JSClipboardCustom.cpp:
  • bindings/js/JSConsoleCustom.cpp:
  • bindings/js/JSCustomSQLStatementCallback.cpp: (WebCore::JSCustomSQLStatementCallback::handleEvent):
  • bindings/js/JSCustomSQLStatementCallback.h: (WebCore::JSCustomSQLStatementCallback::create):
  • bindings/js/JSCustomSQLStatementErrorCallback.cpp: (WebCore::JSCustomSQLStatementErrorCallback::handleEvent):
  • bindings/js/JSCustomSQLStatementErrorCallback.h: (WebCore::JSCustomSQLStatementErrorCallback::create):
  • bindings/js/JSCustomSQLTransactionCallback.cpp: (WebCore::JSCustomSQLTransactionCallback::handleEvent):
  • bindings/js/JSCustomSQLTransactionCallback.h: (WebCore::JSCustomSQLTransactionCallback::create):
  • bindings/js/JSCustomSQLTransactionErrorCallback.cpp: (WebCore::JSCustomSQLTransactionErrorCallback::handleEvent):
  • bindings/js/JSCustomSQLTransactionErrorCallback.h: (WebCore::JSCustomSQLTransactionErrorCallback::create):
  • bindings/js/JSCustomVoidCallback.cpp: (WebCore::JSCustomVoidCallback::handleEvent):
  • bindings/js/JSCustomVoidCallback.h: (WebCore::JSCustomVoidCallback::create):
  • bindings/js/JSCustomXPathNSResolver.cpp: (WebCore::JSCustomXPathNSResolver::create):
  • bindings/js/JSCustomXPathNSResolver.h:
  • bindings/js/JSDOMApplicationCacheCustom.cpp: (WebCore::JSDOMApplicationCache::dispatchEvent):
  • bindings/js/JSDOMBinding.cpp: (WebCore::jsOwnedStringOrNull):
  • bindings/js/JSDOMBinding.h: (WebCore::DOMObject::DOMObject): (WebCore::cacheDOMObject): (WebCore::cacheSVGDOMObject): (WebCore::DOMExceptionTranslator::DOMExceptionTranslator): (WebCore::toJS):
  • bindings/js/JSDOMWindowBase.cpp:
  • bindings/js/JSDOMWindowBase.h: (WebCore::JSDOMWindowBase::classInfo): (WebCore::JSDOMWindowBase::d):
  • bindings/js/JSDOMWindowCustom.cpp: (WebCore::JSDOMWindow::getPropertyAttributes):
  • bindings/js/JSDOMWindowCustom.h: (WebCore::asJSDOMWindow): (WebCore::JSDOMWindow::customGetOwnPropertySlot): (WebCore::JSDOMWindow::customPut): (WebCore::JSDOMWindowBase::allowsAccessFrom): (WebCore::JSDOMWindowBase::allowsAccessFromNoErrorMessage):
  • bindings/js/JSDOMWindowShell.cpp: (WebCore::JSDOMWindowShell::getPropertyAttributes):
  • bindings/js/JSDOMWindowShell.h: (WebCore::JSDOMWindowShell::classInfo):
  • bindings/js/JSDatabaseCustom.cpp:
  • bindings/js/JSDocumentCustom.cpp:
  • bindings/js/JSDocumentFragmentCustom.cpp:
  • bindings/js/JSElementCustom.cpp:
  • bindings/js/JSEventCustom.cpp:
  • bindings/js/JSEventListener.cpp:
  • bindings/js/JSEventListener.h: (WebCore::JSUnprotectedEventListener::create): (WebCore::JSEventListener::create):
  • bindings/js/JSEventTargetBase.cpp:
  • bindings/js/JSEventTargetBase.h: (WebCore::JSEventTargetBase::getValueProperty): (WebCore::JSEventTargetBase::putValueProperty): (WebCore::JSEventTargetBase::getOwnPropertySlot): (WebCore::JSEventTargetBase::put): (WebCore::JSEventTargetPrototype::JSEventTargetPrototype): (WebCore::JSEventTargetPrototype::self): (WebCore::JSEventTargetPrototype::getOwnPropertySlot): (WebCore::JSEventTargetPrototype::classInfo):
  • bindings/js/JSEventTargetNode.cpp:
  • bindings/js/JSEventTargetNode.h: (WebCore::JSEventTargetNode::getOwnPropertySlot): (WebCore::JSEventTargetNode::getValueProperty): (WebCore::JSEventTargetNode::put): (WebCore::JSEventTargetNode::putValueProperty):
  • bindings/js/JSHTMLAllCollection.h: (WebCore::JSHTMLAllCollection::JSHTMLAllCollection): (WebCore::JSHTMLAllCollection::toBoolean):
  • bindings/js/JSHTMLAppletElementCustom.cpp:
  • bindings/js/JSHTMLCollectionCustom.cpp:
  • bindings/js/JSHTMLDocumentCustom.cpp:
  • bindings/js/JSHTMLElementCustom.cpp:
  • bindings/js/JSHTMLEmbedElementCustom.cpp:
  • bindings/js/JSHTMLFormElementCustom.cpp:
  • bindings/js/JSHTMLFrameElementCustom.cpp:
  • bindings/js/JSHTMLFrameSetElementCustom.cpp:
  • bindings/js/JSHTMLIFrameElementCustom.cpp:
  • bindings/js/JSHTMLInputElementBase.cpp: (WebCore::JSHTMLInputElementBase::JSHTMLInputElementBase): (WebCore::JSHTMLInputElementBase::getOwnPropertySlot):
  • bindings/js/JSHTMLInputElementBase.h: (WebCore::JSHTMLInputElementBase::classInfo):
  • bindings/js/JSHTMLObjectElementCustom.cpp:
  • bindings/js/JSHTMLOptionElementConstructor.cpp:
  • bindings/js/JSHTMLOptionElementConstructor.h: (WebCore::JSHTMLOptionElementConstructor::classInfo):
  • bindings/js/JSHTMLOptionsCollectionCustom.cpp:
  • bindings/js/JSHTMLSelectElementCustom.cpp: (WebCore::selectIndexSetter): (WebCore::JSHTMLSelectElement::indexSetter):
  • bindings/js/JSHTMLSelectElementCustom.h:
  • bindings/js/JSHistoryCustom.cpp:
  • bindings/js/JSImageConstructor.cpp:
  • bindings/js/JSImageConstructor.h: (WebCore::JSImageConstructor::classInfo):
  • bindings/js/JSInspectedObjectWrapper.cpp:
  • bindings/js/JSInspectedObjectWrapper.h: (WebCore::JSInspectedObjectWrapper::wrapOutgoingValue): (WebCore::JSInspectedObjectWrapper::classInfo):
  • bindings/js/JSInspectorCallbackWrapper.cpp:
  • bindings/js/JSInspectorCallbackWrapper.h: (WebCore::JSInspectorCallbackWrapper::classInfo): (WebCore::JSInspectorCallbackWrapper::wrapOutgoingValue):
  • bindings/js/JSJavaScriptCallFrameCustom.cpp:
  • bindings/js/JSLocationCustom.cpp:
  • bindings/js/JSMimeTypeArrayCustom.cpp:
  • bindings/js/JSNSResolver.cpp:
  • bindings/js/JSNSResolver.h: (WebCore::JSNSResolver::create):
  • bindings/js/JSNamedNodeMapCustom.cpp:
  • bindings/js/JSNamedNodesCollection.cpp: (WebCore::JSNamedNodesCollection::JSNamedNodesCollection):
  • bindings/js/JSNamedNodesCollection.h: (WebCore::JSNamedNodesCollection::classInfo):
  • bindings/js/JSNavigatorCustom.cpp:
  • bindings/js/JSNodeCustom.cpp:
  • bindings/js/JSNodeFilterCondition.cpp: (WebCore::JSNodeFilterCondition::acceptNode):
  • bindings/js/JSNodeFilterCondition.h: (WebCore::JSNodeFilterCondition::create):
  • bindings/js/JSNodeFilterCustom.cpp:
  • bindings/js/JSNodeIteratorCustom.cpp:
  • bindings/js/JSNodeListCustom.cpp:
  • bindings/js/JSPluginArrayCustom.cpp:
  • bindings/js/JSPluginCustom.cpp:
  • bindings/js/JSPluginElementFunctions.cpp: (WebCore::getRuntimeObject):
  • bindings/js/JSPluginElementFunctions.h:
  • bindings/js/JSQuarantinedObjectWrapper.cpp: (WebCore::JSQuarantinedObjectWrapper::construct): (WebCore::JSQuarantinedObjectWrapper::call):
  • bindings/js/JSQuarantinedObjectWrapper.h: (WebCore::JSQuarantinedObjectWrapper::unwrappedObject): (WebCore::JSQuarantinedObjectWrapper::unwrappedGlobalObject): (WebCore::JSQuarantinedObjectWrapper::className):
  • bindings/js/JSRGBColor.cpp:
  • bindings/js/JSRGBColor.h: (WebCore::JSRGBColor::classInfo):
  • bindings/js/JSSQLResultSetRowListCustom.cpp:
  • bindings/js/JSSQLTransactionCustom.cpp:
  • bindings/js/JSSVGLazyEventListener.cpp:
  • bindings/js/JSSVGLazyEventListener.h:
  • bindings/js/JSSVGLengthCustom.cpp:
  • bindings/js/JSSVGMatrixCustom.cpp: (WebCore::JSSVGMatrix::inverse): (WebCore::JSSVGMatrix::rotateFromVector):
  • bindings/js/JSSVGPathSegCustom.cpp:
  • bindings/js/JSSVGPathSegListCustom.cpp: (WebCore::JSSVGPathSegList::initialize): (WebCore::JSSVGPathSegList::getItem): (WebCore::JSSVGPathSegList::insertItemBefore): (WebCore::JSSVGPathSegList::replaceItem): (WebCore::JSSVGPathSegList::removeItem): (WebCore::JSSVGPathSegList::appendItem):
  • bindings/js/JSSVGPointListCustom.cpp:
  • bindings/js/JSSVGTransformListCustom.cpp:
  • bindings/js/JSStorageCustom.cpp:
  • bindings/js/JSStyleSheetCustom.cpp:
  • bindings/js/JSStyleSheetListCustom.cpp:
  • bindings/js/JSTextCustom.cpp:
  • bindings/js/JSTreeWalkerCustom.cpp:
  • bindings/js/JSXMLHttpRequestConstructor.cpp:
  • bindings/js/JSXMLHttpRequestConstructor.h: (WebCore::JSXMLHttpRequestConstructor::classInfo):
  • bindings/js/JSXMLHttpRequestCustom.cpp:
  • bindings/js/JSXMLHttpRequestUploadCustom.cpp:
  • bindings/js/JSXSLTProcessorConstructor.cpp:
  • bindings/js/JSXSLTProcessorConstructor.h: (WebCore::JSXSLTProcessorConstructor::classInfo):
  • bindings/js/JSXSLTProcessorCustom.cpp:
  • bindings/js/ScheduledAction.cpp:
  • bindings/js/ScheduledAction.h:
  • bindings/js/ScriptController.cpp: (WebCore::ScriptController::attachDebugger): (WebCore::ScriptController::windowScriptNPObject):
  • bindings/js/ScriptController.h:
  • bindings/js/ScriptControllerGtk.cpp: (WebCore::ScriptController::createScriptInstanceForWidget):
  • bindings/js/ScriptControllerMac.mm: (WebCore::ScriptController::createScriptInstanceForWidget): (WebCore::ScriptController::windowScriptObject): (WebCore::ScriptController::clearPlatformScriptObjects): (WebCore::updateRenderingForBindings): (WebCore::ScriptController::initJavaJSBindings):
  • bindings/js/ScriptControllerQt.cpp: (WebCore::ScriptController::createScriptInstanceForWidget):
  • bindings/js/ScriptControllerWin.cpp: (WebCore::ScriptController::createScriptInstanceForWidget):
  • bindings/js/ScriptControllerWx.cpp: (WebCore::ScriptController::createScriptInstanceForWidget):
  • bindings/js/StringSourceProvider.h: (WebCore::StringSourceProvider::getRange):
  • bindings/objc/DOM.mm: (-[DOMNode JSC::Bindings::]):
  • bindings/objc/DOMInternal.h:
  • bindings/objc/DOMInternal.mm: (-[WebScriptObject _initializeScriptDOMNodeImp]):
  • bindings/objc/DOMUtility.mm: (JSC::createDOMWrapper): (WebCore::createDOMWrapper):
  • bindings/objc/WebScriptObject.mm: (WebCore::createJSWrapper): (-[WebScriptObject _initWithJSObject:JSC::originRootObject:JSC::Bindings::rootObject:JSC::Bindings::]):
  • bindings/objc/WebScriptObjectPrivate.h:
  • bindings/scripts/CodeGeneratorJS.pm:
  • bridge/NP_jsobject.cpp:
  • bridge/NP_jsobject.h:
  • bridge/c/c_class.cpp:
  • bridge/c/c_class.h:
  • bridge/c/c_instance.cpp:
  • bridge/c/c_instance.h:
  • bridge/c/c_runtime.cpp:
  • bridge/c/c_runtime.h:
  • bridge/c/c_utility.cpp:
  • bridge/c/c_utility.h:
  • bridge/jni/jni_class.cpp:
  • bridge/jni/jni_class.h:
  • bridge/jni/jni_instance.cpp:
  • bridge/jni/jni_instance.h:
  • bridge/jni/jni_jsobject.h:
  • bridge/jni/jni_jsobject.mm: (JavaJSObject::call): (JavaJSObject::convertJObjectToValue):
  • bridge/jni/jni_objc.mm: (JSC::Bindings::dispatchJNICall):
  • bridge/jni/jni_runtime.cpp:
  • bridge/jni/jni_runtime.h:
  • bridge/jni/jni_utility.cpp:
  • bridge/jni/jni_utility.h:
  • bridge/npruntime.cpp: (_NPN_GetStringIdentifier):
  • bridge/objc/WebScriptObject.h:
  • bridge/objc/objc_class.h:
  • bridge/objc/objc_class.mm:
  • bridge/objc/objc_instance.h:
  • bridge/objc/objc_instance.mm:
  • bridge/objc/objc_runtime.h:
  • bridge/objc/objc_runtime.mm:
  • bridge/objc/objc_utility.h:
  • bridge/objc/objc_utility.mm:
  • bridge/qt/qt_class.cpp:
  • bridge/qt/qt_class.h:
  • bridge/qt/qt_instance.cpp:
  • bridge/qt/qt_instance.h:
  • bridge/qt/qt_runtime.cpp: (JSC::Bindings::convertQVariantToValue): (JSC::Bindings::):
  • bridge/qt/qt_runtime.h:
  • bridge/runtime.cpp:
  • bridge/runtime.h:
  • bridge/runtime_array.cpp:
  • bridge/runtime_array.h:
  • bridge/runtime_method.cpp:
  • bridge/runtime_method.h:
  • bridge/runtime_object.cpp:
  • bridge/runtime_object.h:
  • bridge/runtime_root.cpp: (JSC::Bindings::RootObject::invalidate): (JSC::Bindings::RootObject::gcProtect): (JSC::Bindings::RootObject::gcUnprotect):
  • bridge/runtime_root.h:
  • bridge/testbindings.cpp:
  • bridge/testbindings.mm:
  • bridge/testqtbindings.cpp:
  • dom/Document.cpp: (WebCore::Document::~Document):
  • dom/NSResolver.h:
  • dom/Node.cpp: (WebCore::Node::setDocument): (WebCore::ResolveNamespaceFunctor::ResolveNamespaceFunctor): (WebCore::resolveNamespacesForSelector): (WebCore::Node::querySelector): (WebCore::Node::querySelectorAll):
  • dom/Node.h:
  • dom/NodeFilter.cpp:
  • dom/NodeFilter.h:
  • dom/NodeFilterCondition.cpp:
  • dom/NodeFilterCondition.h:
  • dom/NodeIterator.cpp:
  • dom/NodeIterator.h:
  • dom/Traversal.cpp:
  • dom/Traversal.h:
  • dom/TreeWalker.cpp:
  • dom/TreeWalker.h:
  • dom/make_names.pl:
  • history/CachedPage.cpp:
  • history/CachedPage.h:
  • html/HTMLPlugInElement.cpp: (WebCore::HTMLPlugInElement::getInstance):
  • html/HTMLPlugInElement.h:
  • loader/FrameLoader.cpp:
  • loader/FrameLoader.h:
  • loader/icon/IconDatabase.cpp: (WebCore::iconDatabase):
  • page/Console.cpp:
  • page/Console.h:
  • page/InspectorController.cpp: (WebCore::XMLHttpRequestResource::XMLHttpRequestResource): (WebCore::XMLHttpRequestResource::~XMLHttpRequestResource): (WebCore::InspectorResource::setXMLHttpRequestProperties): (WebCore::InspectorResource::sourceString): (WebCore::getResourceDocumentNode): (WebCore::search): (WebCore::InspectorController::focusNode): (WebCore::InspectorController::inspectedWindowScriptObjectCleared): (WebCore::InspectorController::addDatabaseScriptResource): (WebCore::InspectorController::resourceRetrievedByXMLHttpRequest):
  • page/InspectorController.h: (WebCore::InspectorController::profiles):
  • page/JavaScriptCallFrame.cpp: (WebCore::JavaScriptCallFrame::scopeChain):
  • page/JavaScriptCallFrame.h: (WebCore::JavaScriptCallFrame::create): (WebCore::JavaScriptCallFrame::update):
  • page/JavaScriptDebugListener.h:
  • page/JavaScriptDebugServer.cpp: (WebCore::dispatchDidParseSource):
  • page/JavaScriptDebugServer.h:
  • page/JavaScriptProfile.cpp:
  • page/JavaScriptProfile.h:
  • page/JavaScriptProfileNode.cpp: (WebCore::getTotalTime): (WebCore::getSelfTime): (WebCore::getTotalPercent): (WebCore::getSelfPercent): (WebCore::getNumberOfCalls): (WebCore::getChildren): (WebCore::getVisible):
  • page/JavaScriptProfileNode.h:
  • page/Page.cpp: (WebCore::Page::setDebuggerForAllPages): (WebCore::Page::setDebugger):
  • page/Page.h: (WebCore::Page::debugger):
  • page/mac/FrameMac.mm:
  • platform/KURL.h: (WebCore::KURL::operator JSC::UString):
  • platform/text/AtomicString.cpp: (WebCore::AtomicString::add): (WebCore::AtomicString::find):
  • platform/text/AtomicString.h: (WebCore::AtomicString::AtomicString):
  • platform/text/PlatformString.h:
  • platform/text/String.cpp: (WebCore::charactersToDouble):
  • platform/win/BString.cpp:
  • platform/win/BString.h:
  • plugins/MimeTypeArray.h:
  • plugins/Plugin.h:
  • plugins/PluginArray.h:
  • plugins/PluginView.cpp: (WebCore::PluginView::start): (WebCore::PluginView::performRequest): (WebCore::PluginView::bindingInstance):
  • plugins/PluginView.h:
  • plugins/gtk/PluginViewGtk.cpp: (WebCore::PluginView::paint): (WebCore::PluginView::handleKeyboardEvent): (WebCore::PluginView::handleMouseEvent): (WebCore::PluginView::setNPWindowRect): (WebCore::PluginView::stop): (WebCore::PluginView::init):
  • plugins/qt/PluginViewQt.cpp: (WebCore::PluginView::setNPWindowRect): (WebCore::PluginView::stop): (WebCore::PluginView::init):
  • plugins/win/PluginViewWin.cpp: (WebCore::PluginView::dispatchNPEvent): (WebCore::PluginView::handleKeyboardEvent): (WebCore::PluginView::handleMouseEvent): (WebCore::PluginView::setNPWindowRect): (WebCore::PluginView::stop):
  • storage/Database.cpp: (WebCore::Database::Database):
  • xml/XMLHttpRequest.cpp: (WebCore::XMLHttpRequest::responseText): (WebCore::XMLHttpRequest::loadRequestAsynchronously): (WebCore::XMLHttpRequest::clearResponse): (WebCore::XMLHttpRequest::dropProtection): (WebCore::XMLHttpRequest::didFinishLoading): (WebCore::XMLHttpRequest::didReceiveData):
  • xml/XMLHttpRequest.h:

WebKit/gtk:

  • webkit/webkitprivate.cpp: (webkit_init):

WebKit/mac:

  • Misc/WebCoreStatistics.mm:
  • Plugins/WebBaseNetscapePluginStream.mm: (-[WebBaseNetscapePluginStream wantsAllStreams]):
  • Plugins/WebBaseNetscapePluginView.mm: (-[WebBaseNetscapePluginView sendEvent:isDrawRect:]): (-[WebBaseNetscapePluginView setWindowIfNecessary]): (-[WebBaseNetscapePluginView start]): (-[WebBaseNetscapePluginView createPluginScriptableObject]): (-[WebBaseNetscapePluginView evaluateJavaScriptPluginRequest:]): (-[WebBaseNetscapePluginView webFrame:didFinishLoadWithReason:]): (-[WebBaseNetscapePluginView loadPluginRequest:]): (-[WebBaseNetscapePluginView _printedPluginBitmap]):
  • Plugins/WebPluginController.mm: (+[WebPluginController plugInViewWithArguments:fromPluginPackage:]): (-[WebPluginController startAllPlugins]): (-[WebPluginController stopAllPlugins]): (-[WebPluginController addPlugin:]): (-[WebPluginController destroyPlugin:]): (-[WebPluginController destroyAllPlugins]):
  • WebView/WebFrame.mm:
  • WebView/WebScriptDebugDelegate.mm:
  • WebView/WebScriptDebugger.h:
  • WebView/WebScriptDebugger.mm:
  • WebView/WebView.mm: (-[WebViewPrivate init]):

WebKit/qt:


  • Api/qwebframe.cpp: (QWebFrame::addToJavaScriptWindowObject): (QWebFrame::evaluateJavaScript):

WebKit/win:

  • WebCoreStatistics.cpp:
  • WebJavaScriptCollector.cpp:
  • WebScriptCallFrame.cpp: (WebScriptCallFrame::jsValueToString):
  • WebScriptCallFrame.h: (WebScriptCallFrame::state):
  • WebView.cpp: (WebView::WebView): (WebView::stringByEvaluatingJavaScriptFromString):

WebKit/wx:

  • WebFrame.cpp: (wxWebFrame::RunScript):
File size: 174.2 KB
Line 
1/*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <[email protected]>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "config.h"
31#include "Machine.h"
32
33#include "BatchedTransitionOptimizer.h"
34#include "CodeBlock.h"
35#include "DebuggerCallFrame.h"
36#include "ExceptionHelpers.h"
37#include "ExecState.h"
38#include "GlobalEvalFunction.h"
39#include "JSActivation.h"
40#include "JSArray.h"
41#include "JSFunction.h"
42#include "JSNotAnObject.h"
43#include "JSPropertyNameIterator.h"
44#include "JSStaticScopeObject.h"
45#include "JSString.h"
46#include "ObjectPrototype.h"
47#include "Parser.h"
48#include "Profiler.h"
49#include "RegExpObject.h"
50#include "RegExpPrototype.h"
51#include "Register.h"
52#include "collector.h"
53#include "debugger.h"
54#include "operations.h"
55#include "SamplingTool.h"
56#include <stdio.h>
57
58#if PLATFORM(DARWIN)
59#include <mach/mach.h>
60#endif
61
62#if HAVE(SYS_TIME_H)
63#include <sys/time.h>
64#endif
65
66#if PLATFORM(WIN_OS)
67#include <windows.h>
68#endif
69
70#if PLATFORM(QT)
71#include <QDateTime>
72#endif
73
74using namespace std;
75
76namespace JSC {
77
78// Preferred number of milliseconds between each timeout check
79static const int preferredScriptCheckTimeInterval = 1000;
80
81#if HAVE(COMPUTED_GOTO)
82static void* op_throw_end_indirect;
83static void* op_call_indirect;
84#endif
85
86// Returns the depth of the scope chain within a given call frame.
87static int depth(CodeBlock* codeBlock, ScopeChain& sc)
88{
89 if (!codeBlock->needsFullScopeChain)
90 return 0;
91 int scopeDepth = 0;
92 ScopeChainIterator iter = sc.begin();
93 ScopeChainIterator end = sc.end();
94 while (!(*iter)->isActivationObject()) {
95 ++iter;
96 if (iter == end)
97 break;
98 ++scopeDepth;
99 }
100 return scopeDepth;
101}
102
103// FIXME: This operation should be called "getNumber", not "isNumber" (as it is in JSValue.h).
104// FIXME: There's no need to have a "slow" version of this. All versions should be fast.
105static bool fastIsNumber(JSValue* value, double& arg)
106{
107 if (JSImmediate::isNumber(value))
108 arg = JSImmediate::getTruncatedInt32(value);
109 else if (Heap::isNumber(static_cast<JSCell*>(value)))
110 arg = static_cast<JSNumberCell*>(value)->value();
111 else
112 return false;
113 return true;
114}
115
116// FIXME: Why doesn't JSValue::toInt32 have the Heap::isNumber optimization?
117static bool fastToInt32(JSValue* value, int32_t& arg)
118{
119 if (JSImmediate::isNumber(value))
120 arg = JSImmediate::getTruncatedInt32(value);
121 else if (Heap::isNumber(static_cast<JSCell*>(value)))
122 arg = static_cast<JSNumberCell*>(value)->toInt32();
123 else
124 return false;
125 return true;
126}
127
128static ALWAYS_INLINE bool fastToUInt32(JSValue* value, uint32_t& arg)
129{
130 if (JSImmediate::isNumber(value)) {
131 if (JSImmediate::getTruncatedUInt32(value, arg))
132 return true;
133 bool scratch;
134 arg = JSValue::toUInt32SlowCase(JSImmediate::getTruncatedInt32(value), scratch);
135 return true;
136 } else if (Heap::isNumber(static_cast<JSCell*>(value)))
137 arg = static_cast<JSNumberCell*>(value)->toUInt32();
138 else
139 return false;
140 return true;
141}
142
143static inline bool jsLess(ExecState* exec, JSValue* v1, JSValue* v2)
144{
145 if (JSImmediate::areBothImmediateNumbers(v1, v2))
146 return JSImmediate::getTruncatedInt32(v1) < JSImmediate::getTruncatedInt32(v2);
147
148 double n1;
149 double n2;
150 if (fastIsNumber(v1, n1) && fastIsNumber(v2, n2))
151 return n1 < n2;
152
153 JSValue* p1;
154 JSValue* p2;
155 bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
156 bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
157
158 if (wasNotString1 | wasNotString2)
159 return n1 < n2;
160
161 return static_cast<const JSString*>(p1)->value() < static_cast<const JSString*>(p2)->value();
162}
163
164static inline bool jsLessEq(ExecState* exec, JSValue* v1, JSValue* v2)
165{
166 if (JSImmediate::areBothImmediateNumbers(v1, v2))
167 return JSImmediate::getTruncatedInt32(v1) <= JSImmediate::getTruncatedInt32(v2);
168
169 double n1;
170 double n2;
171 if (fastIsNumber(v1, n1) && fastIsNumber(v2, n2))
172 return n1 <= n2;
173
174 JSValue* p1;
175 JSValue* p2;
176 bool wasNotString1 = v1->getPrimitiveNumber(exec, n1, p1);
177 bool wasNotString2 = v2->getPrimitiveNumber(exec, n2, p2);
178
179 if (wasNotString1 | wasNotString2)
180 return n1 <= n2;
181
182 return !(static_cast<const JSString*>(p2)->value() < static_cast<const JSString*>(p1)->value());
183}
184
185static JSValue* jsAddSlowCase(ExecState* exec, JSValue* v1, JSValue* v2)
186{
187 // exception for the Date exception in defaultValue()
188 JSValue* p1 = v1->toPrimitive(exec);
189 JSValue* p2 = v2->toPrimitive(exec);
190
191 if (p1->isString() || p2->isString()) {
192 RefPtr<UString::Rep> value = concatenate(p1->toString(exec).rep(), p2->toString(exec).rep());
193 if (!value)
194 return throwOutOfMemoryError(exec);
195 return jsString(exec, value.release());
196 }
197
198 return jsNumber(exec, p1->toNumber(exec) + p2->toNumber(exec));
199}
200
201// Fast-path choices here are based on frequency data from SunSpider:
202// <times> Add case: <t1> <t2>
203// ---------------------------
204// 5626160 Add case: 3 3 (of these, 3637690 are for immediate values)
205// 247412 Add case: 5 5
206// 20900 Add case: 5 6
207// 13962 Add case: 5 3
208// 4000 Add case: 3 5
209
210static inline JSValue* jsAdd(ExecState* exec, JSValue* v1, JSValue* v2)
211{
212 double left;
213 double right;
214 if (fastIsNumber(v1, left) && fastIsNumber(v2, right))
215 return jsNumber(exec, left + right);
216
217 if (v1->isString() && v2->isString()) {
218 RefPtr<UString::Rep> value = concatenate(static_cast<JSString*>(v1)->value().rep(), static_cast<JSString*>(v2)->value().rep());
219 if (!value)
220 return throwOutOfMemoryError(exec);
221 return jsString(exec, value.release());
222 }
223
224 // All other cases are pretty uncommon
225 return jsAddSlowCase(exec, v1, v2);
226}
227
228static JSValue* jsTypeStringForValue(ExecState* exec, JSValue* v)
229{
230 if (v->isUndefined())
231 return jsNontrivialString(exec, "undefined");
232 if (v->isBoolean())
233 return jsNontrivialString(exec, "boolean");
234 if (v->isNumber())
235 return jsNontrivialString(exec, "number");
236 if (v->isString())
237 return jsNontrivialString(exec, "string");
238 if (v->isObject()) {
239 // Return "undefined" for objects that should be treated
240 // as null when doing comparisons.
241 if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
242 return jsNontrivialString(exec, "undefined");
243 CallData callData;
244 if (static_cast<JSObject*>(v)->getCallData(callData) != CallTypeNone)
245 return jsNontrivialString(exec, "function");
246 }
247 return jsNontrivialString(exec, "object");
248}
249
250static bool NEVER_INLINE resolve(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
251{
252 int dst = (vPC + 1)->u.operand;
253 int property = (vPC + 2)->u.operand;
254
255 ScopeChainIterator iter = scopeChain->begin();
256 ScopeChainIterator end = scopeChain->end();
257 ASSERT(iter != end);
258
259 Identifier& ident = codeBlock->identifiers[property];
260 do {
261 JSObject* o = *iter;
262 PropertySlot slot(o);
263 if (o->getPropertySlot(exec, ident, slot)) {
264 JSValue* result = slot.getValue(exec, ident);
265 exceptionValue = exec->exception();
266 if (exceptionValue)
267 return false;
268 r[dst] = result;
269 return true;
270 }
271 } while (++iter != end);
272 exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
273 return false;
274}
275
276static bool NEVER_INLINE resolve_skip(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
277{
278 int dst = (vPC + 1)->u.operand;
279 int property = (vPC + 2)->u.operand;
280 int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain;
281
282 ScopeChainIterator iter = scopeChain->begin();
283 ScopeChainIterator end = scopeChain->end();
284 ASSERT(iter != end);
285 while (skip--) {
286 ++iter;
287 ASSERT(iter != end);
288 }
289 Identifier& ident = codeBlock->identifiers[property];
290 do {
291 JSObject* o = *iter;
292 PropertySlot slot(o);
293 if (o->getPropertySlot(exec, ident, slot)) {
294 JSValue* result = slot.getValue(exec, ident);
295 exceptionValue = exec->exception();
296 if (exceptionValue)
297 return false;
298 r[dst] = result;
299 return true;
300 }
301 } while (++iter != end);
302 exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
303 return false;
304}
305
306ALWAYS_INLINE static JSValue* inlineResolveBase(ExecState* exec, Identifier& property, ScopeChainNode* scopeChain)
307{
308 ScopeChainIterator iter = scopeChain->begin();
309 ScopeChainIterator next = iter;
310 ++next;
311 ScopeChainIterator end = scopeChain->end();
312 ASSERT(iter != end);
313
314 PropertySlot slot;
315 JSObject* base;
316 while (true) {
317 base = *iter;
318 if (next == end || base->getPropertySlot(exec, property, slot))
319 return base;
320
321 iter = next;
322 ++next;
323 }
324
325 ASSERT_NOT_REACHED();
326 return 0;
327}
328
329NEVER_INLINE static void resolveBase(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock)
330{
331 int dst = (vPC + 1)->u.operand;
332 int property = (vPC + 2)->u.operand;
333 r[dst] = inlineResolveBase(exec, codeBlock->identifiers[property], scopeChain);
334}
335
336static bool NEVER_INLINE resolveBaseAndProperty(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
337{
338 int baseDst = (vPC + 1)->u.operand;
339 int propDst = (vPC + 2)->u.operand;
340 int property = (vPC + 3)->u.operand;
341
342 ScopeChainIterator iter = scopeChain->begin();
343 ScopeChainIterator end = scopeChain->end();
344
345 // FIXME: add scopeDepthIsZero optimization
346
347 ASSERT(iter != end);
348
349 Identifier& ident = codeBlock->identifiers[property];
350 JSObject* base;
351 do {
352 base = *iter;
353 PropertySlot slot(base);
354 if (base->getPropertySlot(exec, ident, slot)) {
355 JSValue* result = slot.getValue(exec, ident);
356 exceptionValue = exec->exception();
357 if (exceptionValue)
358 return false;
359 r[propDst] = result;
360 r[baseDst] = base;
361 return true;
362 }
363 ++iter;
364 } while (iter != end);
365
366 exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
367 return false;
368}
369
370static bool NEVER_INLINE resolveBaseAndFunc(ExecState* exec, Instruction* vPC, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue*& exceptionValue)
371{
372 int baseDst = (vPC + 1)->u.operand;
373 int funcDst = (vPC + 2)->u.operand;
374 int property = (vPC + 3)->u.operand;
375
376 ScopeChainIterator iter = scopeChain->begin();
377 ScopeChainIterator end = scopeChain->end();
378
379 // FIXME: add scopeDepthIsZero optimization
380
381 ASSERT(iter != end);
382
383 Identifier& ident = codeBlock->identifiers[property];
384 JSObject* base;
385 do {
386 base = *iter;
387 PropertySlot slot(base);
388 if (base->getPropertySlot(exec, ident, slot)) {
389 // ECMA 11.2.3 says that if we hit an activation the this value should be null.
390 // However, section 10.2.3 says that in the case where the value provided
391 // by the caller is null, the global object should be used. It also says
392 // that the section does not apply to internal functions, but for simplicity
393 // of implementation we use the global object anyway here. This guarantees
394 // that in host objects you always get a valid object for this.
395 // We also handle wrapper substitution for the global object at the same time.
396 JSObject* thisObj = base->toThisObject(exec);
397 JSValue* result = slot.getValue(exec, ident);
398 exceptionValue = exec->exception();
399 if (exceptionValue)
400 return false;
401
402 r[baseDst] = thisObj;
403 r[funcDst] = result;
404 return true;
405 }
406 ++iter;
407 } while (iter != end);
408
409 exceptionValue = createUndefinedVariableError(exec, ident, vPC, codeBlock);
410 return false;
411}
412
413ALWAYS_INLINE void Machine::initializeCallFrame(Register* callFrame, CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, Register* r, int returnValueRegister, int argv, int argc, int calledAsConstructor, JSValue* function)
414{
415 callFrame[RegisterFile::CallerCodeBlock] = codeBlock;
416 callFrame[RegisterFile::ReturnVPC] = vPC + 1;
417 callFrame[RegisterFile::CallerScopeChain] = scopeChain;
418 callFrame[RegisterFile::CallerRegisters] = r;
419 callFrame[RegisterFile::ReturnValueRegister] = returnValueRegister;
420 callFrame[RegisterFile::ArgumentStartRegister] = argv; // original argument vector (for the sake of the "arguments" object)
421 callFrame[RegisterFile::ArgumentCount] = argc; // original argument count (for the sake of the "arguments" object)
422 callFrame[RegisterFile::CalledAsConstructor] = calledAsConstructor;
423 callFrame[RegisterFile::Callee] = function;
424 callFrame[RegisterFile::OptionalCalleeActivation] = nullJSValue;
425}
426
427ALWAYS_INLINE Register* slideRegisterWindowForCall(ExecState* exec, CodeBlock* newCodeBlock, RegisterFile* registerFile, Register* registerBase, Register* r, int argv, int argc, JSValue*& exceptionValue)
428{
429 size_t registerOffset = argv + newCodeBlock->numLocals;
430 size_t size = r - registerBase + registerOffset + newCodeBlock->numConstants + newCodeBlock->numTemporaries;
431
432 if (argc == newCodeBlock->numParameters) { // correct number of arguments
433 if (!registerFile->grow(size)) {
434 exceptionValue = createStackOverflowError(exec);
435 return r;
436 }
437 r += registerOffset;
438 } else if (argc < newCodeBlock->numParameters) { // too few arguments -- fill in the blanks
439 if (!registerFile->grow(size)) {
440 exceptionValue = createStackOverflowError(exec);
441 return r;
442 }
443 r += registerOffset;
444
445 int omittedArgCount = newCodeBlock->numParameters - argc;
446 Register* endOfParams = r - newCodeBlock->numVars;
447 for (Register* it = endOfParams - omittedArgCount; it != endOfParams; ++it)
448 (*it) = jsUndefined();
449 } else { // too many arguments -- copy return info and expected arguments, leaving the extra arguments behind
450 int shift = argc + RegisterFile::CallFrameHeaderSize;
451 registerOffset += shift;
452 size += shift;
453
454 if (!registerFile->grow(size)) {
455 exceptionValue = createStackOverflowError(exec);
456 return r;
457 }
458 r += registerOffset;
459
460 Register* it = r - newCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize - shift;
461 Register* end = it + RegisterFile::CallFrameHeaderSize + newCodeBlock->numParameters;
462 for ( ; it != end; ++it)
463 *(it + shift) = *it;
464 }
465
466 // initialize local variable slots
467 for (Register* it = r - newCodeBlock->numVars; it != r; ++it)
468 (*it) = jsUndefined();
469
470 for (size_t i = 0; i < newCodeBlock->constantRegisters.size(); ++i)
471 r[i] = newCodeBlock->constantRegisters[i];
472
473 return r;
474}
475
476ALWAYS_INLINE ScopeChainNode* scopeChainForCall(ExecState* exec, FunctionBodyNode* functionBodyNode, CodeBlock* newCodeBlock, ScopeChainNode* callDataScopeChain, Register* r)
477{
478 if (newCodeBlock->needsFullScopeChain) {
479 JSActivation* activation = new (exec) JSActivation(exec, functionBodyNode, r);
480 r[RegisterFile::OptionalCalleeActivation - RegisterFile::CallFrameHeaderSize - newCodeBlock->numLocals] = activation;
481
482 return callDataScopeChain->copy()->push(activation);
483 }
484
485 return callDataScopeChain;
486}
487
488static NEVER_INLINE bool isNotObject(ExecState* exec, bool forInstanceOf, CodeBlock* codeBlock, const Instruction* vPC, JSValue* value, JSValue*& exceptionData)
489{
490 if (value->isObject())
491 return false;
492 exceptionData = createInvalidParamError(exec, forInstanceOf ? "instanceof" : "in" , value, vPC, codeBlock);
493 return true;
494}
495
496NEVER_INLINE JSValue* Machine::callEval(ExecState* exec, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, Register* r, int argv, int argc, JSValue*& exceptionValue)
497{
498 if (argc < 2)
499 return jsUndefined();
500
501 JSValue* program = r[argv + 1].jsValue(exec);
502
503 if (!program->isString())
504 return program;
505
506 Profiler** profiler = Profiler::enabledProfilerReference();
507 if (*profiler)
508 (*profiler)->willExecute(exec, scopeChain->globalObject()->evalFunction());
509
510 int sourceId;
511 int errLine;
512 UString errMsg;
513 RefPtr<EvalNode> evalNode = exec->parser()->parse<EvalNode>(exec, UString(), 1, UStringSourceProvider::create(static_cast<JSString*>(program)->value()), &sourceId, &errLine, &errMsg);
514
515 if (!evalNode) {
516 exceptionValue = Error::create(exec, SyntaxError, errMsg, errLine, sourceId, NULL);
517 if (*profiler)
518 (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
519 return 0;
520 }
521
522 JSValue* result = exec->globalData().machine->execute(evalNode.get(), exec, thisObj, r - registerFile->base() + argv + argc, scopeChain, &exceptionValue);
523
524 if (*profiler)
525 (*profiler)->didExecute(exec, scopeChain->globalObject()->evalFunction());
526
527 return result;
528}
529
530Machine::Machine()
531 : m_sampler(0)
532#if ENABLE(CTI)
533 , m_ctiArrayLengthTrampoline(0)
534 , m_ctiStringLengthTrampoline(0)
535 , m_jitCodeBuffer(new JITCodeBuffer(1024 * 1024))
536#endif
537 , m_reentryDepth(0)
538 , m_timeoutTime(0)
539 , m_timeAtLastCheckTimeout(0)
540 , m_timeExecuting(0)
541 , m_timeoutCheckCount(0)
542 , m_ticksUntilNextTimeoutCheck(initialTickCountThreshold)
543{
544 privateExecute(InitializeAndReturn);
545
546 // Bizarrely, calling fastMalloc here is faster than allocating space on the stack.
547 void* storage = fastMalloc(sizeof(CollectorBlock));
548
549 JSArray* jsArray = new (storage) JSArray(StructureID::create(jsNull()));
550 m_jsArrayVptr = jsArray->vptr();
551 static_cast<JSCell*>(jsArray)->~JSCell();
552
553 JSString* jsString = new (storage) JSString("");
554 m_jsStringVptr = jsString->vptr();
555 static_cast<JSCell*>(jsString)->~JSCell();
556
557 JSFunction* jsFunction = new (storage) JSFunction(StructureID::create(jsNull()));
558 m_jsFunctionVptr = jsFunction->vptr();
559 static_cast<JSCell*>(jsFunction)->~JSCell();
560
561 fastFree(storage);
562}
563
564Machine::~Machine()
565{
566#if ENABLE(CTI)
567 if (m_ctiArrayLengthTrampoline)
568 fastFree(m_ctiArrayLengthTrampoline);
569 if (m_ctiStringLengthTrampoline)
570 fastFree(m_ctiStringLengthTrampoline);
571#endif
572}
573
574#ifndef NDEBUG
575
576void Machine::dumpCallFrame(const CodeBlock* codeBlock, ScopeChainNode* scopeChain, RegisterFile* registerFile, const Register* r)
577{
578 ScopeChain sc(scopeChain);
579 JSGlobalObject* globalObject = sc.globalObject();
580 codeBlock->dump(globalObject->globalExec());
581 dumpRegisters(codeBlock, registerFile, r);
582}
583
584void Machine::dumpRegisters(const CodeBlock* codeBlock, RegisterFile* registerFile, const Register* r)
585{
586 printf("Register frame: \n\n");
587 printf("----------------------------------------------------\n");
588 printf(" use | address | value \n");
589 printf("----------------------------------------------------\n");
590
591 const Register* it;
592 const Register* end;
593
594 if (codeBlock->codeType == GlobalCode) {
595 it = registerFile->lastGlobal();
596 end = it + registerFile->numGlobals();
597 while (it != end) {
598 printf("[global var] | %10p | %10p \n", it, (*it).v());
599 ++it;
600 }
601 printf("----------------------------------------------------\n");
602 }
603
604 it = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
605 printf("[CallerCodeBlock] | %10p | %10p \n", it, (*it).v()); ++it;
606 printf("[ReturnVPC] | %10p | %10p \n", it, (*it).v()); ++it;
607 printf("[CallerScopeChain] | %10p | %10p \n", it, (*it).v()); ++it;
608 printf("[CallerRegisterOffset] | %10p | %10p \n", it, (*it).v()); ++it;
609 printf("[ReturnValueRegister] | %10p | %10p \n", it, (*it).v()); ++it;
610 printf("[ArgumentStartRegister] | %10p | %10p \n", it, (*it).v()); ++it;
611 printf("[ArgumentCount] | %10p | %10p \n", it, (*it).v()); ++it;
612 printf("[CalledAsConstructor] | %10p | %10p \n", it, (*it).v()); ++it;
613 printf("[Callee] | %10p | %10p \n", it, (*it).v()); ++it;
614 printf("[OptionalCalleeActivation] | %10p | %10p \n", it, (*it).v()); ++it;
615 printf("----------------------------------------------------\n");
616
617 printf("[this] | %10p | %10p \n", it, (*it).v()); ++it;
618 end = it + max(codeBlock->numParameters - 1, 0); // - 1 to skip "this"
619 if (it != end) {
620 do {
621 printf("[param] | %10p | %10p \n", it, (*it).v());
622 ++it;
623 } while (it != end);
624 }
625 printf("----------------------------------------------------\n");
626
627 if (codeBlock->codeType != GlobalCode) {
628 end = it + codeBlock->numVars;
629 if (it != end) {
630 do {
631 printf("[var] | %10p | %10p \n", it, (*it).v());
632 ++it;
633 } while (it != end);
634 printf("----------------------------------------------------\n");
635 }
636 }
637
638 end = it + codeBlock->numTemporaries;
639 if (it != end) {
640 do {
641 printf("[temp] | %10p | %10p \n", it, (*it).v());
642 ++it;
643 } while (it != end);
644 }
645}
646
647#endif
648
649//#if !defined(NDEBUG) || ENABLE(SAMPLING_TOOL)
650
651bool Machine::isOpcode(Opcode opcode)
652{
653#if HAVE(COMPUTED_GOTO)
654 return opcode != HashTraits<Opcode>::emptyValue()
655 && !HashTraits<Opcode>::isDeletedValue(opcode)
656 && m_opcodeIDTable.contains(opcode);
657#else
658 return opcode >= 0 && opcode <= op_end;
659#endif
660}
661
662//#endif
663
664NEVER_INLINE bool Machine::unwindCallFrame(ExecState* exec, JSValue* exceptionValue, const Instruction*& vPC, CodeBlock*& codeBlock, ScopeChainNode*& scopeChain, Register*& r)
665{
666 CodeBlock* oldCodeBlock = codeBlock;
667 Register* callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
668
669 if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
670 DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
671 if (callFrame[RegisterFile::Callee].jsValue(exec))
672 debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
673 else
674 debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->lastLine());
675 }
676
677 if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
678 if (callFrame[RegisterFile::Callee].jsValue(exec))
679 profiler->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
680 else
681 profiler->didExecute(exec, codeBlock->ownerNode->sourceURL(), codeBlock->ownerNode->lineNo());
682 }
683
684 if (oldCodeBlock->needsFullScopeChain)
685 scopeChain->deref();
686
687 // If this call frame created an activation, tear it off.
688 if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
689 ASSERT(activation->isActivationObject());
690 activation->copyRegisters();
691 }
692
693 codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
694 if (!codeBlock)
695 return false;
696
697 scopeChain = callFrame[RegisterFile::CallerScopeChain].scopeChain();
698 r = callFrame[RegisterFile::CallerRegisters].r();
699 exec->m_callFrame = r - oldCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
700 vPC = callFrame[RegisterFile::ReturnVPC].vPC();
701
702 return true;
703}
704
705NEVER_INLINE Instruction* Machine::throwException(ExecState* exec, JSValue*& exceptionValue, const Instruction* vPC, CodeBlock*& codeBlock, ScopeChainNode*& scopeChain, Register*& r, bool explicitThrow)
706{
707 // Set up the exception object
708
709 if (exceptionValue->isObject()) {
710 JSObject* exception = static_cast<JSObject*>(exceptionValue);
711 if (exception->isNotAnObjectErrorStub()) {
712 exception = createNotAnObjectError(exec, static_cast<JSNotAnObjectErrorStub*>(exception), vPC, codeBlock);
713 exceptionValue = exception;
714 } else {
715 if (!exception->hasProperty(exec, Identifier(exec, "line")) &&
716 !exception->hasProperty(exec, Identifier(exec, "sourceId")) &&
717 !exception->hasProperty(exec, Identifier(exec, "sourceURL")) &&
718 !exception->hasProperty(exec, Identifier(exec, expressionBeginOffsetPropertyName)) &&
719 !exception->hasProperty(exec, Identifier(exec, expressionCaretOffsetPropertyName)) &&
720 !exception->hasProperty(exec, Identifier(exec, expressionEndOffsetPropertyName))) {
721 if (explicitThrow) {
722 int startOffset = 0;
723 int endOffset = 0;
724 int divotPoint = 0;
725 int line = codeBlock->expressionRangeForVPC(vPC, divotPoint, startOffset, endOffset);
726 exception->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, line), ReadOnly | DontDelete);
727
728 // We only hit this path for error messages and throw statements, which don't have a specific failure position
729 // So we just give the full range of the error/throw statement.
730 exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
731 exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
732 } else
733 exception->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, codeBlock->lineNumberForVPC(vPC)), ReadOnly | DontDelete);
734 exception->putWithAttributes(exec, Identifier(exec, "sourceId"), jsNumber(exec, codeBlock->ownerNode->sourceId()), ReadOnly | DontDelete);
735 exception->putWithAttributes(exec, Identifier(exec, "sourceURL"), jsOwnedString(exec, codeBlock->ownerNode->sourceURL()), ReadOnly | DontDelete);
736 }
737
738 if (exception->isWatchdogException()) {
739 while (unwindCallFrame(exec, exceptionValue, vPC, codeBlock, scopeChain, r)) {
740 // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
741 }
742 return 0;
743 }
744 }
745 }
746
747 if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) {
748 DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, exceptionValue);
749 debugger->exception(debuggerCallFrame, codeBlock->ownerNode->sourceId(), codeBlock->lineNumberForVPC(vPC));
750 }
751
752 // Calculate an exception handler vPC, unwinding call frames as necessary.
753
754 int scopeDepth;
755 Instruction* handlerVPC;
756
757 while (!codeBlock->getHandlerForVPC(vPC, handlerVPC, scopeDepth)) {
758 if (!unwindCallFrame(exec, exceptionValue, vPC, codeBlock, scopeChain, r))
759 return 0;
760 }
761
762 // Now unwind the scope chain within the exception handler's call frame.
763
764 ScopeChain sc(scopeChain);
765 int scopeDelta = depth(codeBlock, sc) - scopeDepth;
766 ASSERT(scopeDelta >= 0);
767 while (scopeDelta--)
768 sc.pop();
769 setScopeChain(exec, scopeChain, sc.node());
770
771 return handlerVPC;
772}
773
774JSValue* Machine::execute(ProgramNode* programNode, ExecState* exec, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue** exception)
775{
776 if (m_reentryDepth >= MaxReentryDepth) {
777 *exception = createStackOverflowError(exec);
778 return 0;
779 }
780
781 CodeBlock* codeBlock = &programNode->byteCode(scopeChain);
782
783 size_t oldSize = m_registerFile.size();
784 size_t newSize = oldSize + RegisterFile::CallFrameHeaderSize + codeBlock->numVars + codeBlock->numConstants + codeBlock->numTemporaries;
785 if (!m_registerFile.grow(newSize)) {
786 *exception = createStackOverflowError(exec);
787 return 0;
788 }
789
790 JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
791 JSGlobalObject* globalObject = exec->dynamicGlobalObject();
792 globalObject->copyGlobalsTo(m_registerFile);
793
794 Register* callFrame = m_registerFile.base() + oldSize;
795
796 // a 0 codeBlock indicates a built-in caller
797 initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0, 0);
798
799 Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
800 r[codeBlock->thisRegister] = thisObj;
801
802 for (size_t i = 0; i < codeBlock->constantRegisters.size(); ++i)
803 r[i] = codeBlock->constantRegisters[i];
804
805 if (codeBlock->needsFullScopeChain)
806 scopeChain = scopeChain->copy();
807
808 ExecState newExec(exec, &m_registerFile, scopeChain, 0);
809
810 Profiler** profiler = Profiler::enabledProfilerReference();
811 if (*profiler)
812 (*profiler)->willExecute(exec, programNode->sourceURL(), programNode->lineNo());
813
814 m_reentryDepth++;
815#if ENABLE(CTI)
816 if (!codeBlock->ctiCode)
817 CTI::compile(this, exec, codeBlock);
818 JSValue* result = CTI::execute(codeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
819#else
820 JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
821#endif
822 m_reentryDepth--;
823
824 MACHINE_SAMPLING_privateExecuteReturned();
825
826 if (*profiler)
827 (*profiler)->didExecute(exec, programNode->sourceURL(), programNode->lineNo());
828
829 if (m_reentryDepth && lastGlobalObject && globalObject != lastGlobalObject)
830 lastGlobalObject->copyGlobalsTo(m_registerFile);
831
832 m_registerFile.shrink(oldSize);
833 return result;
834}
835
836JSValue* Machine::execute(FunctionBodyNode* functionBodyNode, ExecState* exec, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue** exception)
837{
838 if (m_reentryDepth >= MaxReentryDepth) {
839 *exception = createStackOverflowError(exec);
840 return 0;
841 }
842
843 int argv = RegisterFile::CallFrameHeaderSize;
844 int argc = args.size() + 1; // implicit "this" parameter
845
846 size_t oldSize = m_registerFile.size();
847 if (!m_registerFile.grow(oldSize + RegisterFile::CallFrameHeaderSize + argc)) {
848 *exception = createStackOverflowError(exec);
849 return 0;
850 }
851
852 Register* callFrame = m_registerFile.base() + oldSize;
853
854 // put args in place, including "this"
855 Register* dst = callFrame + RegisterFile::CallFrameHeaderSize;
856 (*dst) = thisObj;
857
858 ArgList::const_iterator end = args.end();
859 for (ArgList::const_iterator it = args.begin(); it != end; ++it)
860 (*++dst) = *it;
861
862 // a 0 codeBlock indicates a built-in caller
863 initializeCallFrame(callFrame, 0, 0, 0, callFrame, 0, argv, argc, 0, function);
864
865 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(scopeChain);
866 Register* r = slideRegisterWindowForCall(exec, newCodeBlock, &m_registerFile, m_registerFile.base(), callFrame, argv, argc, *exception);
867 if (*exception) {
868 m_registerFile.shrink(oldSize);
869 return 0;
870 }
871
872 scopeChain = scopeChainForCall(exec, functionBodyNode, newCodeBlock, scopeChain, r);
873
874 ExecState newExec(exec, &m_registerFile, scopeChain, callFrame);
875
876 Profiler** profiler = Profiler::enabledProfilerReference();
877 if (*profiler)
878 (*profiler)->willExecute(exec, function);
879
880 m_reentryDepth++;
881#if ENABLE(CTI)
882 if (!newCodeBlock->ctiCode)
883 CTI::compile(this, exec, newCodeBlock);
884 JSValue* result = CTI::execute(newCodeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, newCodeBlock, exception);
885#else
886 JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, newCodeBlock, exception);
887#endif
888 m_reentryDepth--;
889
890 MACHINE_SAMPLING_privateExecuteReturned();
891
892 m_registerFile.shrink(oldSize);
893 return result;
894}
895
896JSValue* Machine::execute(EvalNode* evalNode, ExecState* exec, JSObject* thisObj, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)
897{
898 if (m_reentryDepth >= MaxReentryDepth) {
899 *exception = createStackOverflowError(exec);
900 return 0;
901 }
902
903 EvalCodeBlock* codeBlock = &evalNode->byteCode(scopeChain);
904
905 JSVariableObject* variableObject;
906 for (ScopeChainNode* node = scopeChain; ; node = node->next) {
907 ASSERT(node);
908 if (node->object->isVariableObject()) {
909 variableObject = static_cast<JSVariableObject*>(node->object);
910 break;
911 }
912 }
913
914 { // Scope for BatchedTransitionOptimizer
915
916 BatchedTransitionOptimizer optimizer(variableObject);
917
918 const Node::VarStack& varStack = codeBlock->ownerNode->varStack();
919 Node::VarStack::const_iterator varStackEnd = varStack.end();
920 for (Node::VarStack::const_iterator it = varStack.begin(); it != varStackEnd; ++it) {
921 const Identifier& ident = (*it).first;
922 if (!variableObject->hasProperty(exec, ident)) {
923 PutPropertySlot slot;
924 variableObject->put(exec, ident, jsUndefined(), slot);
925 }
926 }
927
928 const Node::FunctionStack& functionStack = codeBlock->ownerNode->functionStack();
929 Node::FunctionStack::const_iterator functionStackEnd = functionStack.end();
930 for (Node::FunctionStack::const_iterator it = functionStack.begin(); it != functionStackEnd; ++it) {
931 PutPropertySlot slot;
932 variableObject->put(exec, (*it)->m_ident, (*it)->makeFunction(exec, scopeChain), slot);
933 }
934
935 }
936
937 size_t oldSize = m_registerFile.size();
938 size_t newSize = registerOffset + codeBlock->numVars + codeBlock->numConstants + codeBlock->numTemporaries + RegisterFile::CallFrameHeaderSize;
939 if (!m_registerFile.grow(newSize)) {
940 *exception = createStackOverflowError(exec);
941 return 0;
942 }
943
944 Register* callFrame = m_registerFile.base() + registerOffset;
945
946 // a 0 codeBlock indicates a built-in caller
947 initializeCallFrame(callFrame, 0, 0, 0, 0, 0, 0, 0, 0, 0);
948
949 Register* r = callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numVars;
950 r[codeBlock->thisRegister] = thisObj;
951
952 for (size_t i = 0; i < codeBlock->constantRegisters.size(); ++i)
953 r[i] = codeBlock->constantRegisters[i];
954
955 if (codeBlock->needsFullScopeChain)
956 scopeChain = scopeChain->copy();
957
958 ExecState newExec(exec, &m_registerFile, scopeChain, 0);
959
960 Profiler** profiler = Profiler::enabledProfilerReference();
961 if (*profiler)
962 (*profiler)->willExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
963
964 m_reentryDepth++;
965#if ENABLE(CTI)
966 if (!codeBlock->ctiCode)
967 CTI::compile(this, exec, codeBlock);
968 JSValue* result = CTI::execute(codeBlock->ctiCode, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
969#else
970 JSValue* result = privateExecute(Normal, &newExec, &m_registerFile, r, scopeChain, codeBlock, exception);
971#endif
972 m_reentryDepth--;
973
974 MACHINE_SAMPLING_privateExecuteReturned();
975
976 if (*profiler)
977 (*profiler)->didExecute(exec, evalNode->sourceURL(), evalNode->lineNo());
978
979 m_registerFile.shrink(oldSize);
980 return result;
981}
982
983ALWAYS_INLINE void Machine::setScopeChain(ExecState* exec, ScopeChainNode*& scopeChain, ScopeChainNode* newScopeChain)
984{
985 scopeChain = newScopeChain;
986 exec->m_scopeChain = newScopeChain;
987}
988
989NEVER_INLINE void Machine::debug(ExecState* exec, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register* r, DebugHookID debugHookID, int firstLine, int lastLine)
990{
991 Debugger* debugger = exec->dynamicGlobalObject()->debugger();
992 if (!debugger)
993 return;
994
995 DebuggerCallFrame debuggerCallFrame(exec, exec->dynamicGlobalObject(), codeBlock, scopeChain, r, 0);
996
997 switch (debugHookID) {
998 case DidEnterCallFrame:
999 debugger->callEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
1000 return;
1001 case WillLeaveCallFrame:
1002 debugger->returnEvent(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
1003 return;
1004 case WillExecuteStatement:
1005 debugger->atStatement(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
1006 return;
1007 case WillExecuteProgram:
1008 debugger->willExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), firstLine);
1009 return;
1010 case DidExecuteProgram:
1011 debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
1012 return;
1013 case DidReachBreakpoint:
1014 debugger->didReachBreakpoint(debuggerCallFrame, codeBlock->ownerNode->sourceId(), lastLine);
1015 return;
1016 }
1017}
1018
1019void Machine::resetTimeoutCheck()
1020{
1021 m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
1022 m_timeAtLastCheckTimeout = 0;
1023 m_timeExecuting = 0;
1024}
1025
1026// Returns the time the current thread has spent executing, in milliseconds.
1027static inline unsigned getCPUTime()
1028{
1029#if PLATFORM(DARWIN)
1030 mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT;
1031 thread_basic_info_data_t info;
1032
1033 // Get thread information
1034 thread_info(mach_thread_self(), THREAD_BASIC_INFO, reinterpret_cast<thread_info_t>(&info), &infoCount);
1035
1036 unsigned time = info.user_time.seconds * 1000 + info.user_time.microseconds / 1000;
1037 time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000;
1038
1039 return time;
1040#elif HAVE(SYS_TIME_H)
1041 // FIXME: This should probably use getrusage with the RUSAGE_THREAD flag.
1042 struct timeval tv;
1043 gettimeofday(&tv, 0);
1044 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
1045#elif PLATFORM(QT)
1046 QDateTime t = QDateTime::currentDateTime();
1047 return t.toTime_t() * 1000 + t.time().msec();
1048#elif PLATFORM(WIN_OS)
1049 union {
1050 FILETIME fileTime;
1051 unsigned long long fileTimeAsLong;
1052 } userTime, kernelTime;
1053
1054 // GetThreadTimes won't accept NULL arguments so we pass these even though
1055 // they're not used.
1056 FILETIME creationTime, exitTime;
1057
1058 GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime);
1059
1060 return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000;
1061#else
1062#error Platform does not have getCurrentTime function
1063#endif
1064}
1065
1066// We have to return a JSValue here, gcc seems to produce worse code if
1067// we attempt to return a bool
1068ALWAYS_INLINE JSValue* Machine::checkTimeout(JSGlobalObject* globalObject)
1069{
1070 unsigned currentTime = getCPUTime();
1071
1072 if (!m_timeAtLastCheckTimeout) {
1073 // Suspicious amount of looping in a script -- start timing it
1074 m_timeAtLastCheckTimeout = currentTime;
1075 return 0;
1076 }
1077
1078 unsigned timeDiff = currentTime - m_timeAtLastCheckTimeout;
1079
1080 if (timeDiff == 0)
1081 timeDiff = 1;
1082
1083 m_timeExecuting += timeDiff;
1084 m_timeAtLastCheckTimeout = currentTime;
1085
1086 // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in
1087 // preferredScriptCheckTimeInterval
1088 m_ticksUntilNextTimeoutCheck = static_cast<unsigned>((static_cast<float>(preferredScriptCheckTimeInterval) / timeDiff) * m_ticksUntilNextTimeoutCheck);
1089 // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the
1090 // preferred script check time interval.
1091 if (m_ticksUntilNextTimeoutCheck == 0)
1092 m_ticksUntilNextTimeoutCheck = initialTickCountThreshold;
1093
1094 if (m_timeoutTime && m_timeExecuting > m_timeoutTime) {
1095 if (globalObject->shouldInterruptScript())
1096 return jsNull(); // Appeasing GCC, all we need is a non-null js value.
1097
1098 resetTimeoutCheck();
1099 }
1100
1101 return 0;
1102}
1103
1104static NEVER_INLINE ScopeChainNode* createExceptionScope(ExecState* exec, CodeBlock* codeBlock, const Instruction* vPC, Register* r, ScopeChainNode* scopeChain)
1105{
1106 int dst = (++vPC)->u.operand;
1107 Identifier& property = codeBlock->identifiers[(++vPC)->u.operand];
1108 JSValue* value = r[(++vPC)->u.operand].jsValue(exec);
1109 JSObject* scope = new (exec) JSStaticScopeObject(exec, property, value, DontDelete);
1110 r[dst] = scope;
1111 return scopeChain->push(scope);
1112}
1113
1114StructureIDChain* cachePrototypeChain(StructureID* structureID)
1115{
1116 RefPtr<StructureIDChain> chain = StructureIDChain::create(static_cast<JSObject*>(structureID->prototype())->structureID());
1117 structureID->setCachedPrototypeChain(chain.release());
1118 return structureID->cachedPrototypeChain();
1119}
1120
1121NEVER_INLINE void Machine::tryCachePutByID(CodeBlock* codeBlock, Instruction* vPC, JSValue* baseValue, const PutPropertySlot& slot)
1122{
1123 // Recursive invocation may already have specialized this instruction.
1124 if (vPC[0].u.opcode != getOpcode(op_put_by_id))
1125 return;
1126
1127 if (JSImmediate::isImmediate(baseValue))
1128 return;
1129
1130 // Uncacheable: give up.
1131 if (!slot.isCacheable()) {
1132 vPC[0] = getOpcode(op_put_by_id_generic);
1133 return;
1134 }
1135
1136 // FIXME: Cache new property transitions, too.
1137 if (slot.type() == PutPropertySlot::NewProperty) {
1138 vPC[0] = getOpcode(op_put_by_id_generic);
1139 return;
1140 }
1141
1142 JSCell* baseCell = static_cast<JSCell*>(baseValue);
1143 StructureID* structureID = baseCell->structureID();
1144
1145 // FIXME: Remove this !structureID check once all objects have StructureIDs.
1146 if (!structureID) {
1147 vPC[0] = getOpcode(op_put_by_id_generic);
1148 return;
1149 }
1150
1151 if (structureID->isDictionary()) {
1152 vPC[0] = getOpcode(op_put_by_id_generic);
1153 return;
1154 }
1155
1156 // Cache miss: record StructureID to compare against next time.
1157 StructureID* lastStructureID = vPC[4].u.structureID;
1158 if (structureID != lastStructureID) {
1159 // First miss: record StructureID to compare against next time.
1160 if (!lastStructureID) {
1161 vPC[4] = structureID;
1162 return;
1163 }
1164
1165 // Second miss: give up.
1166 vPC[0] = getOpcode(op_put_by_id_generic);
1167 return;
1168 }
1169
1170 // Cache hit: Specialize instruction and ref StructureIDs.
1171
1172 // If baseCell != slot.base(), then baseCell must be a proxy for another object.
1173 if (baseCell != slot.base()) {
1174 vPC[0] = getOpcode(op_put_by_id_generic);
1175 return;
1176 }
1177 vPC[0] = getOpcode(op_put_by_id_replace);
1178 vPC[5] = slot.cachedOffset();
1179 codeBlock->refStructureIDs(vPC);
1180}
1181
1182NEVER_INLINE void Machine::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC)
1183{
1184 codeBlock->derefStructureIDs(vPC);
1185 vPC[0] = getOpcode(op_put_by_id);
1186 vPC[4] = 0;
1187}
1188
1189NEVER_INLINE void Machine::tryCacheGetByID(ExecState* exec, CodeBlock* codeBlock, Instruction* vPC, JSValue* baseValue, const Identifier& propertyName, const PropertySlot& slot)
1190{
1191 // Recursive invocation may already have specialized this instruction.
1192 if (vPC[0].u.opcode != getOpcode(op_get_by_id))
1193 return;
1194
1195 if (isJSArray(baseValue) && propertyName == exec->propertyNames().length) {
1196 vPC[0] = getOpcode(op_get_array_length);
1197 return;
1198 }
1199
1200 if (isJSString(baseValue) && propertyName == exec->propertyNames().length) {
1201 vPC[0] = getOpcode(op_get_string_length);
1202 return;
1203 }
1204
1205 // Uncacheable: give up.
1206 if (!slot.isCacheable()) {
1207 vPC[0] = getOpcode(op_get_by_id_generic);
1208 return;
1209 }
1210
1211 // FIXME: Cache property access for immediates.
1212 if (JSImmediate::isImmediate(baseValue)) {
1213 vPC[0] = getOpcode(op_get_by_id_generic);
1214 return;
1215 }
1216
1217 StructureID* structureID = static_cast<JSCell*>(baseValue)->structureID();
1218
1219 // FIXME: Remove this !structureID check once all JSCells have StructureIDs.
1220 if (!structureID) {
1221 vPC[0] = getOpcode(op_get_by_id_generic);
1222 return;
1223 }
1224
1225 if (structureID->isDictionary()) {
1226 vPC[0] = getOpcode(op_get_by_id_generic);
1227 return;
1228 }
1229
1230 // Cache miss
1231 StructureID* lastStructureID = vPC[4].u.structureID;
1232 if (structureID != lastStructureID) {
1233 // First miss: record StructureID to compare against next time.
1234 if (!lastStructureID) {
1235 vPC[4] = structureID;
1236 return;
1237 }
1238
1239 // Second miss: give up.
1240 vPC[0] = getOpcode(op_get_by_id_generic);
1241 return;
1242 }
1243
1244 // Cache hit: Specialize instruction and ref StructureIDs.
1245
1246 if (slot.slotBase() == baseValue) {
1247 vPC[0] = getOpcode(op_get_by_id_self);
1248 vPC[5] = slot.cachedOffset();
1249
1250 codeBlock->refStructureIDs(vPC);
1251 return;
1252 }
1253
1254 if (slot.slotBase() == structureID->prototype()) {
1255 ASSERT(slot.slotBase()->isObject());
1256
1257 JSObject* baseObject = static_cast<JSObject*>(slot.slotBase());
1258
1259 // Heavy access to a prototype is a good indication that it's not being
1260 // used as a dictionary.
1261 if (baseObject->structureID()->isDictionary()) {
1262 RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(baseObject->structureID());
1263 baseObject->setStructureID(transition.release());
1264 static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
1265 }
1266
1267 vPC[0] = getOpcode(op_get_by_id_proto);
1268 vPC[5] = baseObject->structureID();
1269 vPC[6] = slot.cachedOffset();
1270
1271 codeBlock->refStructureIDs(vPC);
1272 return;
1273 }
1274
1275 size_t count = 0;
1276 JSObject* o = static_cast<JSObject*>(baseValue);
1277 while (slot.slotBase() != o) {
1278 JSValue* v = o->structureID()->prototype();
1279
1280 // If we didn't find base in baseValue's prototype chain, then baseValue
1281 // must be a proxy for another object.
1282 if (v->isNull()) {
1283 vPC[0] = getOpcode(op_get_by_id_generic);
1284 return;
1285 }
1286
1287 o = static_cast<JSObject*>(v);
1288
1289 // Heavy access to a prototype is a good indication that it's not being
1290 // used as a dictionary.
1291 if (o->structureID()->isDictionary()) {
1292 RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(o->structureID());
1293 o->setStructureID(transition.release());
1294 static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
1295 }
1296
1297 ++count;
1298 }
1299
1300 StructureIDChain* chain = structureID->cachedPrototypeChain();
1301 if (!chain)
1302 chain = cachePrototypeChain(structureID);
1303
1304 vPC[0] = getOpcode(op_get_by_id_chain);
1305 vPC[4] = structureID;
1306 vPC[5] = chain;
1307 vPC[6] = count;
1308 vPC[7] = slot.cachedOffset();
1309 codeBlock->refStructureIDs(vPC);
1310}
1311
1312NEVER_INLINE void Machine::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC)
1313{
1314 codeBlock->derefStructureIDs(vPC);
1315 vPC[0] = getOpcode(op_get_by_id);
1316 vPC[4] = 0;
1317}
1318
1319JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception)
1320{
1321 // One-time initialization of our address tables. We have to put this code
1322 // here because our labels are only in scope inside this function.
1323 if (flag == InitializeAndReturn) {
1324 #if HAVE(COMPUTED_GOTO)
1325 #define ADD_OPCODE(id) m_opcodeTable[id] = &&id;
1326 FOR_EACH_OPCODE_ID(ADD_OPCODE);
1327 #undef ADD_OPCODE
1328
1329 #define ADD_OPCODE_ID(id) m_opcodeIDTable.add(&&id, id);
1330 FOR_EACH_OPCODE_ID(ADD_OPCODE_ID);
1331 #undef ADD_OPCODE_ID
1332 ASSERT(m_opcodeIDTable.size() == numOpcodeIDs);
1333 op_throw_end_indirect = &&op_throw_end;
1334 op_call_indirect = &&op_call;
1335 #endif // HAVE(COMPUTED_GOTO)
1336 return 0;
1337 }
1338
1339#if ENABLE(CTI)
1340 // Currently with CTI enabled we never interpret functions
1341 ASSERT_NOT_REACHED();
1342#endif
1343
1344 JSValue* exceptionValue = 0;
1345 Instruction* handlerVPC = 0;
1346
1347 Register* registerBase = registerFile->base();
1348 Instruction* vPC = codeBlock->instructions.begin();
1349 Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
1350 unsigned tickCount = m_ticksUntilNextTimeoutCheck + 1;
1351
1352#define VM_CHECK_EXCEPTION() \
1353 do { \
1354 if (UNLIKELY(exec->hadException())) { \
1355 exceptionValue = exec->exception(); \
1356 goto vm_throw; \
1357 } \
1358 } while (0)
1359
1360#if DUMP_OPCODE_STATS
1361 OpcodeStats::resetLastInstruction();
1362#endif
1363
1364#define CHECK_FOR_TIMEOUT() \
1365 if (!--tickCount) { \
1366 if ((exceptionValue = checkTimeout(exec->dynamicGlobalObject()))) \
1367 goto vm_throw; \
1368 tickCount = m_ticksUntilNextTimeoutCheck; \
1369 }
1370
1371#if HAVE(COMPUTED_GOTO)
1372 #define NEXT_OPCODE MACHINE_SAMPLING_sample(codeBlock, vPC); goto *vPC->u.opcode
1373#if DUMP_OPCODE_STATS
1374 #define BEGIN_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
1375#else
1376 #define BEGIN_OPCODE(opcode) opcode:
1377#endif
1378 NEXT_OPCODE;
1379#else
1380 #define NEXT_OPCODE MACHINE_SAMPLING_sample(codeBlock, vPC); continue
1381#if DUMP_OPCODE_STATS
1382 #define BEGIN_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
1383#else
1384 #define BEGIN_OPCODE(opcode) case opcode:
1385#endif
1386 while (1) // iterator loop begins
1387 switch (vPC->u.opcode)
1388#endif
1389 {
1390 BEGIN_OPCODE(op_new_object) {
1391 /* new_object dst(r)
1392
1393 Constructs a new empty Object instance using the original
1394 constructor, and puts the result in register dst.
1395 */
1396 int dst = (++vPC)->u.operand;
1397 r[dst] = constructEmptyObject(exec);
1398
1399 ++vPC;
1400 NEXT_OPCODE;
1401 }
1402 BEGIN_OPCODE(op_new_array) {
1403 /* new_array dst(r) firstArg(r) argCount(n)
1404
1405 Constructs a new Array instance using the original
1406 constructor, and puts the result in register dst.
1407 The array will contain argCount elements with values
1408 taken from registers starting at register firstArg.
1409 */
1410 int dst = (++vPC)->u.operand;
1411 int firstArg = (++vPC)->u.operand;
1412 int argCount = (++vPC)->u.operand;
1413 ArgList args(r + firstArg, argCount);
1414 r[dst] = constructArray(exec, args);
1415
1416 ++vPC;
1417 NEXT_OPCODE;
1418 }
1419 BEGIN_OPCODE(op_new_regexp) {
1420 /* new_regexp dst(r) regExp(re)
1421
1422 Constructs a new RegExp instance using the original
1423 constructor from regexp regExp, and puts the result in
1424 register dst.
1425 */
1426 int dst = (++vPC)->u.operand;
1427 int regExp = (++vPC)->u.operand;
1428 r[dst] = new (exec) RegExpObject(scopeChain->globalObject()->regExpPrototype(), codeBlock->regexps[regExp]);
1429
1430 ++vPC;
1431 NEXT_OPCODE;
1432 }
1433 BEGIN_OPCODE(op_mov) {
1434 /* mov dst(r) src(r)
1435
1436 Copies register src to register dst.
1437 */
1438 int dst = (++vPC)->u.operand;
1439 int src = (++vPC)->u.operand;
1440 r[dst] = r[src];
1441
1442 ++vPC;
1443 NEXT_OPCODE;
1444 }
1445 BEGIN_OPCODE(op_eq) {
1446 /* eq dst(r) src1(r) src2(r)
1447
1448 Checks whether register src1 and register src2 are equal,
1449 as with the ECMAScript '==' operator, and puts the result
1450 as a boolean in register dst.
1451 */
1452 int dst = (++vPC)->u.operand;
1453 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1454 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1455 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1456 r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1457 else {
1458 JSValue* result = jsBoolean(equal(exec, src1, src2));
1459 VM_CHECK_EXCEPTION();
1460 r[dst] = result;
1461 }
1462
1463 ++vPC;
1464 NEXT_OPCODE;
1465 }
1466 BEGIN_OPCODE(op_eq_null) {
1467 /* neq dst(r) src(r)
1468
1469 Checks whether register src is null, as with the ECMAScript '!='
1470 operator, and puts the result as a boolean in register dst.
1471 */
1472 int dst = (++vPC)->u.operand;
1473 JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
1474
1475 if (src->isUndefinedOrNull()) {
1476 r[dst] = jsBoolean(true);
1477 ++vPC;
1478 NEXT_OPCODE;
1479 }
1480
1481 r[dst] = jsBoolean(!JSImmediate::isImmediate(src) && static_cast<JSCell*>(src)->masqueradeAsUndefined());
1482 ++vPC;
1483 NEXT_OPCODE;
1484 }
1485 BEGIN_OPCODE(op_neq) {
1486 /* neq dst(r) src1(r) src2(r)
1487
1488 Checks whether register src1 and register src2 are not
1489 equal, as with the ECMAScript '!=' operator, and puts the
1490 result as a boolean in register dst.
1491 */
1492 int dst = (++vPC)->u.operand;
1493 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1494 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1495 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1496 r[dst] = jsBoolean(src1 != src2);
1497 else {
1498 JSValue* result = jsBoolean(!equal(exec, src1, src2));
1499 VM_CHECK_EXCEPTION();
1500 r[dst] = result;
1501 }
1502
1503 ++vPC;
1504 NEXT_OPCODE;
1505 }
1506 BEGIN_OPCODE(op_neq_null) {
1507 /* neq dst(r) src(r)
1508
1509 Checks whether register src is not null, as with the ECMAScript '!='
1510 operator, and puts the result as a boolean in register dst.
1511 */
1512 int dst = (++vPC)->u.operand;
1513 JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
1514
1515 if (src->isUndefinedOrNull()) {
1516 r[dst] = jsBoolean(false);
1517 ++vPC;
1518 NEXT_OPCODE;
1519 }
1520
1521 r[dst] = jsBoolean(JSImmediate::isImmediate(src) || !static_cast<JSCell*>(src)->masqueradeAsUndefined());
1522 ++vPC;
1523 NEXT_OPCODE;
1524 }
1525 BEGIN_OPCODE(op_stricteq) {
1526 /* stricteq dst(r) src1(r) src2(r)
1527
1528 Checks whether register src1 and register src2 are strictly
1529 equal, as with the ECMAScript '===' operator, and puts the
1530 result as a boolean in register dst.
1531 */
1532 int dst = (++vPC)->u.operand;
1533 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1534 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1535 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1536 r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
1537 else
1538 r[dst] = jsBoolean(strictEqual(src1, src2));
1539
1540 ++vPC;
1541 NEXT_OPCODE;
1542 }
1543 BEGIN_OPCODE(op_nstricteq) {
1544 /* nstricteq dst(r) src1(r) src2(r)
1545
1546 Checks whether register src1 and register src2 are not
1547 strictly equal, as with the ECMAScript '!==' operator, and
1548 puts the result as a boolean in register dst.
1549 */
1550 int dst = (++vPC)->u.operand;
1551 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1552 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1553 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1554 r[dst] = jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
1555 else
1556 r[dst] = jsBoolean(!strictEqual(src1, src2));
1557
1558 ++vPC;
1559 NEXT_OPCODE;
1560 }
1561 BEGIN_OPCODE(op_less) {
1562 /* less dst(r) src1(r) src2(r)
1563
1564 Checks whether register src1 is less than register src2, as
1565 with the ECMAScript '<' operator, and puts the result as
1566 a boolean in register dst.
1567 */
1568 int dst = (++vPC)->u.operand;
1569 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1570 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1571 JSValue* result = jsBoolean(jsLess(exec, src1, src2));
1572 VM_CHECK_EXCEPTION();
1573 r[dst] = result;
1574
1575 ++vPC;
1576 NEXT_OPCODE;
1577 }
1578 BEGIN_OPCODE(op_lesseq) {
1579 /* lesseq dst(r) src1(r) src2(r)
1580
1581 Checks whether register src1 is less than or equal to
1582 register src2, as with the ECMAScript '<=' operator, and
1583 puts the result as a boolean in register dst.
1584 */
1585 int dst = (++vPC)->u.operand;
1586 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1587 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1588 JSValue* result = jsBoolean(jsLessEq(exec, src1, src2));
1589 VM_CHECK_EXCEPTION();
1590 r[dst] = result;
1591
1592 ++vPC;
1593 NEXT_OPCODE;
1594 }
1595 BEGIN_OPCODE(op_pre_inc) {
1596 /* pre_inc srcDst(r)
1597
1598 Converts register srcDst to number, adds one, and puts the result
1599 back in register srcDst.
1600 */
1601 int srcDst = (++vPC)->u.operand;
1602 JSValue* v = r[srcDst].jsValue(exec);
1603 if (JSImmediate::canDoFastAdditiveOperations(v))
1604 r[srcDst] = JSImmediate::incImmediateNumber(v);
1605 else {
1606 JSValue* result = jsNumber(exec, v->toNumber(exec) + 1);
1607 VM_CHECK_EXCEPTION();
1608 r[srcDst] = result;
1609 }
1610
1611 ++vPC;
1612 NEXT_OPCODE;
1613 }
1614 BEGIN_OPCODE(op_pre_dec) {
1615 /* pre_dec srcDst(r)
1616
1617 Converts register srcDst to number, subtracts one, and puts the result
1618 back in register srcDst.
1619 */
1620 int srcDst = (++vPC)->u.operand;
1621 JSValue* v = r[srcDst].jsValue(exec);
1622 if (JSImmediate::canDoFastAdditiveOperations(v))
1623 r[srcDst] = JSImmediate::decImmediateNumber(v);
1624 else {
1625 JSValue* result = jsNumber(exec, v->toNumber(exec) - 1);
1626 VM_CHECK_EXCEPTION();
1627 r[srcDst] = result;
1628 }
1629
1630 ++vPC;
1631 NEXT_OPCODE;
1632 }
1633 BEGIN_OPCODE(op_post_inc) {
1634 /* post_inc dst(r) srcDst(r)
1635
1636 Converts register srcDst to number. The number itself is
1637 written to register dst, and the number plus one is written
1638 back to register srcDst.
1639 */
1640 int dst = (++vPC)->u.operand;
1641 int srcDst = (++vPC)->u.operand;
1642 JSValue* v = r[srcDst].jsValue(exec);
1643 if (JSImmediate::canDoFastAdditiveOperations(v)) {
1644 r[dst] = v;
1645 r[srcDst] = JSImmediate::incImmediateNumber(v);
1646 } else {
1647 JSValue* number = r[srcDst].jsValue(exec)->toJSNumber(exec);
1648 VM_CHECK_EXCEPTION();
1649 r[dst] = number;
1650 r[srcDst] = jsNumber(exec, number->uncheckedGetNumber() + 1);
1651 }
1652
1653 ++vPC;
1654 NEXT_OPCODE;
1655 }
1656 BEGIN_OPCODE(op_post_dec) {
1657 /* post_dec dst(r) srcDst(r)
1658
1659 Converts register srcDst to number. The number itself is
1660 written to register dst, and the number minus one is written
1661 back to register srcDst.
1662 */
1663 int dst = (++vPC)->u.operand;
1664 int srcDst = (++vPC)->u.operand;
1665 JSValue* v = r[srcDst].jsValue(exec);
1666 if (JSImmediate::canDoFastAdditiveOperations(v)) {
1667 r[dst] = v;
1668 r[srcDst] = JSImmediate::decImmediateNumber(v);
1669 } else {
1670 JSValue* number = r[srcDst].jsValue(exec)->toJSNumber(exec);
1671 VM_CHECK_EXCEPTION();
1672 r[dst] = number;
1673 r[srcDst] = jsNumber(exec, number->uncheckedGetNumber() - 1);
1674 }
1675
1676 ++vPC;
1677 NEXT_OPCODE;
1678 }
1679 BEGIN_OPCODE(op_to_jsnumber) {
1680 /* to_jsnumber dst(r) src(r)
1681
1682 Converts register src to number, and puts the result
1683 in register dst.
1684 */
1685 int dst = (++vPC)->u.operand;
1686 int src = (++vPC)->u.operand;
1687 JSValue* result = r[src].jsValue(exec)->toJSNumber(exec);
1688 VM_CHECK_EXCEPTION();
1689
1690 r[dst] = result;
1691
1692 ++vPC;
1693 NEXT_OPCODE;
1694 }
1695 BEGIN_OPCODE(op_negate) {
1696 /* negate dst(r) src(r)
1697
1698 Converts register src to number, negates it, and puts the
1699 result in register dst.
1700 */
1701 int dst = (++vPC)->u.operand;
1702 JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
1703 double v;
1704 if (fastIsNumber(src, v))
1705 r[dst] = jsNumber(exec, -v);
1706 else {
1707 JSValue* result = jsNumber(exec, -src->toNumber(exec));
1708 VM_CHECK_EXCEPTION();
1709 r[dst] = result;
1710 }
1711
1712 ++vPC;
1713 NEXT_OPCODE;
1714 }
1715 BEGIN_OPCODE(op_add) {
1716 /* add dst(r) src1(r) src2(r)
1717
1718 Adds register src1 and register src2, and puts the result
1719 in register dst. (JS add may be string concatenation or
1720 numeric add, depending on the types of the operands.)
1721 */
1722 int dst = (++vPC)->u.operand;
1723 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1724 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1725 if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1726 r[dst] = JSImmediate::addImmediateNumbers(src1, src2);
1727 else {
1728 JSValue* result = jsAdd(exec, src1, src2);
1729 VM_CHECK_EXCEPTION();
1730 r[dst] = result;
1731 }
1732 ++vPC;
1733 NEXT_OPCODE;
1734 }
1735 BEGIN_OPCODE(op_mul) {
1736 /* mul dst(r) src1(r) src2(r)
1737
1738 Multiplies register src1 and register src2 (converted to
1739 numbers), and puts the product in register dst.
1740 */
1741 int dst = (++vPC)->u.operand;
1742 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1743 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1744 double left;
1745 double right;
1746 if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
1747 r[dst] = jsNumber(exec, left * right);
1748 else {
1749 JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
1750 VM_CHECK_EXCEPTION();
1751 r[dst] = result;
1752 }
1753
1754 ++vPC;
1755 NEXT_OPCODE;
1756 }
1757 BEGIN_OPCODE(op_div) {
1758 /* div dst(r) dividend(r) divisor(r)
1759
1760 Divides register dividend (converted to number) by the
1761 register divisor (converted to number), and puts the
1762 quotient in register dst.
1763 */
1764 int dst = (++vPC)->u.operand;
1765 JSValue* dividend = r[(++vPC)->u.operand].jsValue(exec);
1766 JSValue* divisor = r[(++vPC)->u.operand].jsValue(exec);
1767 double left;
1768 double right;
1769 if (fastIsNumber(dividend, left) && fastIsNumber(divisor, right))
1770 r[dst] = jsNumber(exec, left / right);
1771 else {
1772 JSValue* result = jsNumber(exec, dividend->toNumber(exec) / divisor->toNumber(exec));
1773 VM_CHECK_EXCEPTION();
1774 r[dst] = result;
1775 }
1776 ++vPC;
1777 NEXT_OPCODE;
1778 }
1779 BEGIN_OPCODE(op_mod) {
1780 /* mod dst(r) dividend(r) divisor(r)
1781
1782 Divides register dividend (converted to number) by
1783 register divisor (converted to number), and puts the
1784 remainder in register dst.
1785 */
1786 int dst = (++vPC)->u.operand;
1787 int dividend = (++vPC)->u.operand;
1788 int divisor = (++vPC)->u.operand;
1789
1790 JSValue* dividendValue = r[dividend].jsValue(exec);
1791 JSValue* divisorValue = r[divisor].jsValue(exec);
1792
1793 if (JSImmediate::areBothImmediateNumbers(dividendValue, divisorValue) && divisorValue != JSImmediate::from(0)) {
1794 r[dst] = JSImmediate::from(JSImmediate::getTruncatedInt32(dividendValue) % JSImmediate::getTruncatedInt32(divisorValue));
1795 ++vPC;
1796 NEXT_OPCODE;
1797 }
1798
1799 double d = dividendValue->toNumber(exec);
1800 JSValue* result = jsNumber(exec, fmod(d, divisorValue->toNumber(exec)));
1801 VM_CHECK_EXCEPTION();
1802 r[dst] = result;
1803 ++vPC;
1804 NEXT_OPCODE;
1805 }
1806 BEGIN_OPCODE(op_sub) {
1807 /* sub dst(r) src1(r) src2(r)
1808
1809 Subtracts register src2 (converted to number) from register
1810 src1 (converted to number), and puts the difference in
1811 register dst.
1812 */
1813 int dst = (++vPC)->u.operand;
1814 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1815 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1816 double left;
1817 double right;
1818 if (JSImmediate::canDoFastAdditiveOperations(src1) && JSImmediate::canDoFastAdditiveOperations(src2))
1819 r[dst] = JSImmediate::subImmediateNumbers(src1, src2);
1820 else if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
1821 r[dst] = jsNumber(exec, left - right);
1822 else {
1823 JSValue* result = jsNumber(exec, src1->toNumber(exec) - src2->toNumber(exec));
1824 VM_CHECK_EXCEPTION();
1825 r[dst] = result;
1826 }
1827 ++vPC;
1828 NEXT_OPCODE;
1829 }
1830 BEGIN_OPCODE(op_lshift) {
1831 /* lshift dst(r) val(r) shift(r)
1832
1833 Performs left shift of register val (converted to int32) by
1834 register shift (converted to uint32), and puts the result
1835 in register dst.
1836 */
1837 int dst = (++vPC)->u.operand;
1838 JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1839 JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1840 int32_t left;
1841 uint32_t right;
1842 if (JSImmediate::areBothImmediateNumbers(val, shift))
1843 r[dst] = jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::getTruncatedUInt32(shift) & 0x1f));
1844 else if (fastToInt32(val, left) && fastToUInt32(shift, right))
1845 r[dst] = jsNumber(exec, left << (right & 0x1f));
1846 else {
1847 JSValue* result = jsNumber(exec, (val->toInt32(exec)) << (shift->toUInt32(exec) & 0x1f));
1848 VM_CHECK_EXCEPTION();
1849 r[dst] = result;
1850 }
1851
1852 ++vPC;
1853 NEXT_OPCODE;
1854 }
1855 BEGIN_OPCODE(op_rshift) {
1856 /* rshift dst(r) val(r) shift(r)
1857
1858 Performs arithmetic right shift of register val (converted
1859 to int32) by register shift (converted to
1860 uint32), and puts the result in register dst.
1861 */
1862 int dst = (++vPC)->u.operand;
1863 JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1864 JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1865 int32_t left;
1866 uint32_t right;
1867 if (JSImmediate::areBothImmediateNumbers(val, shift))
1868 r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
1869 else if (fastToInt32(val, left) && fastToUInt32(shift, right))
1870 r[dst] = jsNumber(exec, left >> (right & 0x1f));
1871 else {
1872 JSValue* result = jsNumber(exec, (val->toInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1873 VM_CHECK_EXCEPTION();
1874 r[dst] = result;
1875 }
1876
1877 ++vPC;
1878 NEXT_OPCODE;
1879 }
1880 BEGIN_OPCODE(op_urshift) {
1881 /* rshift dst(r) val(r) shift(r)
1882
1883 Performs logical right shift of register val (converted
1884 to uint32) by register shift (converted to
1885 uint32), and puts the result in register dst.
1886 */
1887 int dst = (++vPC)->u.operand;
1888 JSValue* val = r[(++vPC)->u.operand].jsValue(exec);
1889 JSValue* shift = r[(++vPC)->u.operand].jsValue(exec);
1890 if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val))
1891 r[dst] = JSImmediate::rightShiftImmediateNumbers(val, shift);
1892 else {
1893 JSValue* result = jsNumber(exec, (val->toUInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
1894 VM_CHECK_EXCEPTION();
1895 r[dst] = result;
1896 }
1897
1898 ++vPC;
1899 NEXT_OPCODE;
1900 }
1901 BEGIN_OPCODE(op_bitand) {
1902 /* bitand dst(r) src1(r) src2(r)
1903
1904 Computes bitwise AND of register src1 (converted to int32)
1905 and register src2 (converted to int32), and puts the result
1906 in register dst.
1907 */
1908 int dst = (++vPC)->u.operand;
1909 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1910 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1911 int32_t left;
1912 int32_t right;
1913 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1914 r[dst] = JSImmediate::andImmediateNumbers(src1, src2);
1915 else if (fastToInt32(src1, left) && fastToInt32(src2, right))
1916 r[dst] = jsNumber(exec, left & right);
1917 else {
1918 JSValue* result = jsNumber(exec, src1->toInt32(exec) & src2->toInt32(exec));
1919 VM_CHECK_EXCEPTION();
1920 r[dst] = result;
1921 }
1922
1923 ++vPC;
1924 NEXT_OPCODE;
1925 }
1926 BEGIN_OPCODE(op_bitxor) {
1927 /* bitxor dst(r) src1(r) src2(r)
1928
1929 Computes bitwise XOR of register src1 (converted to int32)
1930 and register src2 (converted to int32), and puts the result
1931 in register dst.
1932 */
1933 int dst = (++vPC)->u.operand;
1934 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1935 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1936 int32_t left;
1937 int32_t right;
1938 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1939 r[dst] = JSImmediate::xorImmediateNumbers(src1, src2);
1940 else if (fastToInt32(src1, left) && fastToInt32(src2, right))
1941 r[dst] = jsNumber(exec, left ^ right);
1942 else {
1943 JSValue* result = jsNumber(exec, src1->toInt32(exec) ^ src2->toInt32(exec));
1944 VM_CHECK_EXCEPTION();
1945 r[dst] = result;
1946 }
1947
1948 ++vPC;
1949 NEXT_OPCODE;
1950 }
1951 BEGIN_OPCODE(op_bitor) {
1952 /* bitor dst(r) src1(r) src2(r)
1953
1954 Computes bitwise OR of register src1 (converted to int32)
1955 and register src2 (converted to int32), and puts the
1956 result in register dst.
1957 */
1958 int dst = (++vPC)->u.operand;
1959 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
1960 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
1961 int32_t left;
1962 int32_t right;
1963 if (JSImmediate::areBothImmediateNumbers(src1, src2))
1964 r[dst] = JSImmediate::orImmediateNumbers(src1, src2);
1965 else if (fastToInt32(src1, left) && fastToInt32(src2, right))
1966 r[dst] = jsNumber(exec, left | right);
1967 else {
1968 JSValue* result = jsNumber(exec, src1->toInt32(exec) | src2->toInt32(exec));
1969 VM_CHECK_EXCEPTION();
1970 r[dst] = result;
1971 }
1972
1973 ++vPC;
1974 NEXT_OPCODE;
1975 }
1976 BEGIN_OPCODE(op_bitnot) {
1977 /* bitnot dst(r) src(r)
1978
1979 Computes bitwise NOT of register src1 (converted to int32),
1980 and puts the result in register dst.
1981 */
1982 int dst = (++vPC)->u.operand;
1983 JSValue* src = r[(++vPC)->u.operand].jsValue(exec);
1984 int32_t value;
1985 if (fastToInt32(src, value))
1986 r[dst] = jsNumber(exec, ~value);
1987 else {
1988 JSValue* result = jsNumber(exec, ~src->toInt32(exec));
1989 VM_CHECK_EXCEPTION();
1990 r[dst] = result;
1991 }
1992 ++vPC;
1993 NEXT_OPCODE;
1994 }
1995 BEGIN_OPCODE(op_not) {
1996 /* not dst(r) src(r)
1997
1998 Computes logical NOT of register src (converted to
1999 boolean), and puts the result in register dst.
2000 */
2001 int dst = (++vPC)->u.operand;
2002 int src = (++vPC)->u.operand;
2003 JSValue* result = jsBoolean(!r[src].jsValue(exec)->toBoolean(exec));
2004 VM_CHECK_EXCEPTION();
2005 r[dst] = result;
2006
2007 ++vPC;
2008 NEXT_OPCODE;
2009 }
2010 BEGIN_OPCODE(op_instanceof) {
2011 /* instanceof dst(r) value(r) constructor(r)
2012
2013 Tests whether register value is an instance of register
2014 constructor, and puts the boolean result in register dst.
2015
2016 Raises an exception if register constructor is not an
2017 object.
2018 */
2019 int dst = (++vPC)->u.operand;
2020 int value = (++vPC)->u.operand;
2021 int base = (++vPC)->u.operand;
2022
2023 JSValue* baseVal = r[base].jsValue(exec);
2024
2025 if (isNotObject(exec, true, codeBlock, vPC, baseVal, exceptionValue))
2026 goto vm_throw;
2027
2028 JSObject* baseObj = static_cast<JSObject*>(baseVal);
2029 r[dst] = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, r[value].jsValue(exec)) : false);
2030
2031 ++vPC;
2032 NEXT_OPCODE;
2033 }
2034 BEGIN_OPCODE(op_typeof) {
2035 /* typeof dst(r) src(r)
2036
2037 Determines the type string for src according to ECMAScript
2038 rules, and puts the result in register dst.
2039 */
2040 int dst = (++vPC)->u.operand;
2041 int src = (++vPC)->u.operand;
2042 r[dst] = jsTypeStringForValue(exec, r[src].jsValue(exec));
2043
2044 ++vPC;
2045 NEXT_OPCODE;
2046 }
2047 BEGIN_OPCODE(op_in) {
2048 /* in dst(r) property(r) base(r)
2049
2050 Tests whether register base has a property named register
2051 property, and puts the boolean result in register dst.
2052
2053 Raises an exception if register constructor is not an
2054 object.
2055 */
2056 int dst = (++vPC)->u.operand;
2057 int property = (++vPC)->u.operand;
2058 int base = (++vPC)->u.operand;
2059
2060 JSValue* baseVal = r[base].jsValue(exec);
2061 if (isNotObject(exec, false, codeBlock, vPC, baseVal, exceptionValue))
2062 goto vm_throw;
2063
2064 JSObject* baseObj = static_cast<JSObject*>(baseVal);
2065
2066 JSValue* propName = r[property].jsValue(exec);
2067
2068 uint32_t i;
2069 if (propName->getUInt32(i))
2070 r[dst] = jsBoolean(baseObj->hasProperty(exec, i));
2071 else {
2072 Identifier property(exec, propName->toString(exec));
2073 VM_CHECK_EXCEPTION();
2074 r[dst] = jsBoolean(baseObj->hasProperty(exec, property));
2075 }
2076
2077 ++vPC;
2078 NEXT_OPCODE;
2079 }
2080 BEGIN_OPCODE(op_resolve) {
2081 /* resolve dst(r) property(id)
2082
2083 Looks up the property named by identifier property in the
2084 scope chain, and writes the resulting value to register
2085 dst. If the property is not found, raises an exception.
2086 */
2087 if (UNLIKELY(!resolve(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
2088 goto vm_throw;
2089
2090 vPC += 3;
2091 NEXT_OPCODE;
2092 }
2093 BEGIN_OPCODE(op_resolve_skip) {
2094 /* resolve_skip dst(r) property(id) skip(n)
2095
2096 Looks up the property named by identifier property in the
2097 scope chain skipping the top 'skip' levels, and writes the resulting
2098 value to register dst. If the property is not found, raises an exception.
2099 */
2100 if (UNLIKELY(!resolve_skip(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
2101 goto vm_throw;
2102
2103 vPC += 4;
2104
2105 NEXT_OPCODE;
2106 }
2107 BEGIN_OPCODE(op_get_scoped_var) {
2108 /* get_scoped_var dst(r) index(n) skip(n)
2109
2110 Loads the contents of the index-th local from the scope skip nodes from
2111 the top of the scope chain, and places it in register dst
2112 */
2113 int dst = (++vPC)->u.operand;
2114 int index = (++vPC)->u.operand;
2115 int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
2116
2117 ScopeChainIterator iter = scopeChain->begin();
2118 ScopeChainIterator end = scopeChain->end();
2119 ASSERT(iter != end);
2120 while (skip--) {
2121 ++iter;
2122 ASSERT(iter != end);
2123 }
2124
2125 ASSERT((*iter)->isVariableObject());
2126 JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
2127 r[dst] = scope->registerAt(index);
2128 ++vPC;
2129 NEXT_OPCODE;
2130 }
2131 BEGIN_OPCODE(op_put_scoped_var) {
2132 /* put_scoped_var index(n) skip(n) value(r)
2133
2134 */
2135 int index = (++vPC)->u.operand;
2136 int skip = (++vPC)->u.operand + codeBlock->needsFullScopeChain;
2137 int value = (++vPC)->u.operand;
2138
2139 ScopeChainIterator iter = scopeChain->begin();
2140 ScopeChainIterator end = scopeChain->end();
2141 ASSERT(iter != end);
2142 while (skip--) {
2143 ++iter;
2144 ASSERT(iter != end);
2145 }
2146
2147 ASSERT((*iter)->isVariableObject());
2148 JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
2149 scope->registerAt(index) = r[value].jsValue(exec);
2150 ++vPC;
2151 NEXT_OPCODE;
2152 }
2153 BEGIN_OPCODE(op_resolve_base) {
2154 /* resolve_base dst(r) property(id)
2155
2156 Searches the scope chain for an object containing
2157 identifier property, and if one is found, writes it to
2158 register dst. If none is found, the outermost scope (which
2159 will be the global object) is stored in register dst.
2160 */
2161 resolveBase(exec, vPC, r, scopeChain, codeBlock);
2162
2163 vPC += 3;
2164 NEXT_OPCODE;
2165 }
2166 BEGIN_OPCODE(op_resolve_with_base) {
2167 /* resolve_with_base baseDst(r) propDst(r) property(id)
2168
2169 Searches the scope chain for an object containing
2170 identifier property, and if one is found, writes it to
2171 register srcDst, and the retrieved property value to register
2172 propDst. If the property is not found, raises an exception.
2173
2174 This is more efficient than doing resolve_base followed by
2175 resolve, or resolve_base followed by get_by_id, as it
2176 avoids duplicate hash lookups.
2177 */
2178 if (UNLIKELY(!resolveBaseAndProperty(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
2179 goto vm_throw;
2180
2181 vPC += 4;
2182 NEXT_OPCODE;
2183 }
2184 BEGIN_OPCODE(op_resolve_func) {
2185 /* resolve_func baseDst(r) funcDst(r) property(id)
2186
2187 Searches the scope chain for an object containing
2188 identifier property, and if one is found, writes the
2189 appropriate object to use as "this" when calling its
2190 properties to register baseDst; and the retrieved property
2191 value to register propDst. If the property is not found,
2192 raises an exception.
2193
2194 This differs from resolve_with_base, because the
2195 global this value will be substituted for activations or
2196 the global object, which is the right behavior for function
2197 calls but not for other property lookup.
2198 */
2199 if (UNLIKELY(!resolveBaseAndFunc(exec, vPC, r, scopeChain, codeBlock, exceptionValue)))
2200 goto vm_throw;
2201
2202 vPC += 4;
2203 NEXT_OPCODE;
2204 }
2205 BEGIN_OPCODE(op_get_by_id) {
2206 /* get_by_id dst(r) base(r) property(id) structureID(sID) nop(n) nop(n) nop(n)
2207
2208 Generic property access: Gets the property named by identifier
2209 property from the value base, and puts the result in register dst.
2210 */
2211 int dst = vPC[1].u.operand;
2212 int base = vPC[2].u.operand;
2213 int property = vPC[3].u.operand;
2214
2215 Identifier& ident = codeBlock->identifiers[property];
2216 JSValue* baseValue = r[base].jsValue(exec);
2217 PropertySlot slot(baseValue);
2218 JSValue* result = baseValue->get(exec, ident, slot);
2219 VM_CHECK_EXCEPTION();
2220
2221 tryCacheGetByID(exec, codeBlock, vPC, baseValue, ident, slot);
2222
2223 r[dst] = result;
2224 vPC += 8;
2225 NEXT_OPCODE;
2226 }
2227 BEGIN_OPCODE(op_get_by_id_self) {
2228 /* op_get_by_id_self dst(r) base(r) property(id) structureID(sID) offset(n) nop(n) nop(n)
2229
2230 Cached property access: Attempts to get a cached property from the
2231 value base. If the cache misses, op_get_by_id_self reverts to
2232 op_get_by_id.
2233 */
2234 int base = vPC[2].u.operand;
2235 JSValue* baseValue = r[base].jsValue(exec);
2236
2237 if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2238 JSCell* baseCell = static_cast<JSCell*>(baseValue);
2239 StructureID* structureID = vPC[4].u.structureID;
2240
2241 if (LIKELY(baseCell->structureID() == structureID)) {
2242 ASSERT(baseCell->isObject());
2243 JSObject* baseObject = static_cast<JSObject*>(baseCell);
2244 int dst = vPC[1].u.operand;
2245 int offset = vPC[5].u.operand;
2246
2247 ASSERT(baseObject->get(exec, codeBlock->identifiers[vPC[3].u.operand]) == baseObject->getDirectOffset(offset));
2248 r[dst] = baseObject->getDirectOffset(offset);
2249
2250 vPC += 8;
2251 NEXT_OPCODE;
2252 }
2253 }
2254
2255 uncacheGetByID(codeBlock, vPC);
2256 NEXT_OPCODE;
2257 }
2258 BEGIN_OPCODE(op_get_by_id_proto) {
2259 /* op_get_by_id_proto dst(r) base(r) property(id) structureID(sID) protoStructureID(sID) offset(n) nop(n)
2260
2261 Cached property access: Attempts to get a cached property from the
2262 value base's prototype. If the cache misses, op_get_by_id_proto
2263 reverts to op_get_by_id.
2264 */
2265 int base = vPC[2].u.operand;
2266 JSValue* baseValue = r[base].jsValue(exec);
2267
2268 if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2269 JSCell* baseCell = static_cast<JSCell*>(baseValue);
2270 StructureID* structureID = vPC[4].u.structureID;
2271
2272 if (LIKELY(baseCell->structureID() == structureID)) {
2273 ASSERT(structureID->prototype()->isObject());
2274 JSObject* protoObject = static_cast<JSObject*>(structureID->prototype());
2275 StructureID* protoStructureID = vPC[5].u.structureID;
2276
2277 if (LIKELY(protoObject->structureID() == protoStructureID)) {
2278 int dst = vPC[1].u.operand;
2279 int offset = vPC[6].u.operand;
2280
2281 ASSERT(protoObject->get(exec, codeBlock->identifiers[vPC[3].u.operand]) == protoObject->getDirectOffset(offset));
2282 r[dst] = protoObject->getDirectOffset(offset);
2283
2284 vPC += 8;
2285 NEXT_OPCODE;
2286 }
2287 }
2288 }
2289
2290 uncacheGetByID(codeBlock, vPC);
2291 NEXT_OPCODE;
2292 }
2293 BEGIN_OPCODE(op_get_by_id_chain) {
2294 /* op_get_by_id_chain dst(r) base(r) property(id) structureID(sID) structureIDChain(sIDc) count(n) offset(n)
2295
2296 Cached property access: Attempts to get a cached property from the
2297 value base's prototype chain. If the cache misses, op_get_by_id_chain
2298 reverts to op_get_by_id.
2299 */
2300 int base = vPC[2].u.operand;
2301 JSValue* baseValue = r[base].jsValue(exec);
2302
2303 if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2304 JSCell* baseCell = static_cast<JSCell*>(baseValue);
2305 StructureID* structureID = vPC[4].u.structureID;
2306
2307 if (LIKELY(baseCell->structureID() == structureID)) {
2308 RefPtr<StructureID>* it = vPC[5].u.structureIDChain->head();
2309 size_t count = vPC[6].u.operand;
2310 RefPtr<StructureID>* end = it + count;
2311
2312 while (1) {
2313 ASSERT(baseCell->isObject());
2314 JSObject* baseObject = static_cast<JSObject*>(baseCell->structureID()->prototype());
2315 if (UNLIKELY(baseObject->structureID() != (*it).get()))
2316 break;
2317
2318 if (++it == end) {
2319 int dst = vPC[1].u.operand;
2320 int offset = vPC[7].u.operand;
2321
2322 ASSERT(baseObject->get(exec, codeBlock->identifiers[vPC[3].u.operand]) == baseObject->getDirectOffset(offset));
2323 r[dst] = baseObject->getDirectOffset(offset);
2324
2325 vPC += 8;
2326 NEXT_OPCODE;
2327 }
2328 }
2329 }
2330 }
2331
2332 uncacheGetByID(codeBlock, vPC);
2333 NEXT_OPCODE;
2334 }
2335 BEGIN_OPCODE(op_get_by_id_generic) {
2336 /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2337
2338 Generic property access: Gets the property named by identifier
2339 property from the value base, and puts the result in register dst.
2340 */
2341 int dst = vPC[1].u.operand;
2342 int base = vPC[2].u.operand;
2343 int property = vPC[3].u.operand;
2344
2345 Identifier& ident = codeBlock->identifiers[property];
2346 JSValue* baseValue = r[base].jsValue(exec);
2347 PropertySlot slot(baseValue);
2348 JSValue* result = baseValue->get(exec, ident, slot);
2349 VM_CHECK_EXCEPTION();
2350
2351 r[dst] = result;
2352 vPC += 8;
2353 NEXT_OPCODE;
2354 }
2355 BEGIN_OPCODE(op_get_array_length) {
2356 /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2357
2358 Cached property access: Gets the length of the array in register base,
2359 and puts the result in register dst. If register base does not hold
2360 an array, op_get_array_length reverts to op_get_by_id.
2361 */
2362
2363 int base = vPC[2].u.operand;
2364 JSValue* baseValue = r[base].jsValue(exec);
2365 if (LIKELY(isJSArray(baseValue))) {
2366 int dst = vPC[1].u.operand;
2367 r[dst] = jsNumber(exec, static_cast<JSArray*>(baseValue)->length());
2368 vPC += 8;
2369 NEXT_OPCODE;
2370 }
2371
2372 uncacheGetByID(codeBlock, vPC);
2373 NEXT_OPCODE;
2374 }
2375 BEGIN_OPCODE(op_get_string_length) {
2376 /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
2377
2378 Cached property access: Gets the length of the string in register base,
2379 and puts the result in register dst. If register base does not hold
2380 a string, op_get_string_length reverts to op_get_by_id.
2381 */
2382
2383 int base = vPC[2].u.operand;
2384 JSValue* baseValue = r[base].jsValue(exec);
2385 if (LIKELY(isJSString(baseValue))) {
2386 int dst = vPC[1].u.operand;
2387 r[dst] = jsNumber(exec, static_cast<JSString*>(baseValue)->value().size());
2388 vPC += 8;
2389 NEXT_OPCODE;
2390 }
2391
2392 uncacheGetByID(codeBlock, vPC);
2393 NEXT_OPCODE;
2394 }
2395 BEGIN_OPCODE(op_put_by_id) {
2396 /* put_by_id base(r) property(id) value(r) nop(n) nop(n)
2397
2398 Generic property access: Sets the property named by identifier
2399 property, belonging to register base, to register value.
2400
2401 Unlike many opcodes, this one does not write any output to
2402 the register file.
2403 */
2404
2405 int base = vPC[1].u.operand;
2406 int property = vPC[2].u.operand;
2407 int value = vPC[3].u.operand;
2408
2409 JSValue* baseValue = r[base].jsValue(exec);
2410
2411 PutPropertySlot slot;
2412 Identifier& ident = codeBlock->identifiers[property];
2413 baseValue->put(exec, ident, r[value].jsValue(exec), slot);
2414 VM_CHECK_EXCEPTION();
2415
2416 tryCachePutByID(codeBlock, vPC, baseValue, slot);
2417
2418 vPC += 6;
2419 NEXT_OPCODE;
2420 }
2421 BEGIN_OPCODE(op_put_by_id_replace) {
2422 /* op_put_by_id_replace base(r) property(id) value(r) structureID(sID) offset(n)
2423
2424 Cached property access: Attempts to set a pre-existing, cached
2425 property named by identifier property, belonging to register base,
2426 to register value. If the cache misses, op_put_by_id_replace
2427 reverts to op_put_by_id.
2428
2429 Unlike many opcodes, this one does not write any output to
2430 the register file.
2431 */
2432 int base = vPC[1].u.operand;
2433 JSValue* baseValue = r[base].jsValue(exec);
2434
2435 if (LIKELY(!JSImmediate::isImmediate(baseValue))) {
2436 JSCell* baseCell = static_cast<JSCell*>(baseValue);
2437 StructureID* structureID = vPC[4].u.structureID;
2438
2439 if (LIKELY(baseCell->structureID() == structureID)) {
2440 ASSERT(baseCell->isObject());
2441 JSObject* baseObject = static_cast<JSObject*>(baseCell);
2442 int value = vPC[3].u.operand;
2443 unsigned offset = vPC[5].u.operand;
2444
2445 ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(codeBlock->identifiers[vPC[2].u.operand])) == offset);
2446 baseObject->putDirectOffset(offset, r[value].jsValue(exec));
2447
2448 vPC += 6;
2449 NEXT_OPCODE;
2450 }
2451 }
2452
2453 uncachePutByID(codeBlock, vPC);
2454 NEXT_OPCODE;
2455 }
2456 BEGIN_OPCODE(op_put_by_id_generic) {
2457 /* op_put_by_id_generic base(r) property(id) value(r) nop(n) nop(n)
2458
2459 Generic property access: Sets the property named by identifier
2460 property, belonging to register base, to register value.
2461
2462 Unlike many opcodes, this one does not write any output to
2463 the register file.
2464 */
2465 int base = vPC[1].u.operand;
2466 int property = vPC[2].u.operand;
2467 int value = vPC[3].u.operand;
2468
2469 JSValue* baseValue = r[base].jsValue(exec);
2470
2471 PutPropertySlot slot;
2472 Identifier& ident = codeBlock->identifiers[property];
2473 baseValue->put(exec, ident, r[value].jsValue(exec), slot);
2474 VM_CHECK_EXCEPTION();
2475
2476 vPC += 6;
2477 NEXT_OPCODE;
2478 }
2479 BEGIN_OPCODE(op_del_by_id) {
2480 /* del_by_id dst(r) base(r) property(id)
2481
2482 Converts register base to Object, deletes the property
2483 named by identifier property from the object, and writes a
2484 boolean indicating success (if true) or failure (if false)
2485 to register dst.
2486 */
2487 int dst = (++vPC)->u.operand;
2488 int base = (++vPC)->u.operand;
2489 int property = (++vPC)->u.operand;
2490
2491 JSObject* baseObj = r[base].jsValue(exec)->toObject(exec);
2492
2493 Identifier& ident = codeBlock->identifiers[property];
2494 JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident));
2495 VM_CHECK_EXCEPTION();
2496 r[dst] = result;
2497 ++vPC;
2498 NEXT_OPCODE;
2499 }
2500 BEGIN_OPCODE(op_get_by_val) {
2501 /* get_by_val dst(r) base(r) property(r)
2502
2503 Converts register base to Object, gets the property named
2504 by register property from the object, and puts the result
2505 in register dst. property is nominally converted to string
2506 but numbers are treated more efficiently.
2507 */
2508 int dst = (++vPC)->u.operand;
2509 int base = (++vPC)->u.operand;
2510 int property = (++vPC)->u.operand;
2511
2512 JSValue* baseValue = r[base].jsValue(exec);
2513 JSValue* subscript = r[property].jsValue(exec);
2514
2515 JSValue* result;
2516 unsigned i;
2517
2518 bool isUInt32 = JSImmediate::getUInt32(subscript, i);
2519 if (LIKELY(isUInt32)) {
2520 if (isJSArray(baseValue)) {
2521 JSArray* jsArray = static_cast<JSArray*>(baseValue);
2522 if (jsArray->canGetIndex(i))
2523 result = jsArray->getIndex(i);
2524 else
2525 result = jsArray->JSArray::get(exec, i);
2526 } else if (isJSString(baseValue) && static_cast<JSString*>(baseValue)->canGetIndex(i))
2527 result = static_cast<JSString*>(baseValue)->getIndex(exec, i);
2528 else
2529 result = baseValue->get(exec, i);
2530 } else {
2531 Identifier property(exec, subscript->toString(exec));
2532 result = baseValue->get(exec, property);
2533 }
2534
2535 VM_CHECK_EXCEPTION();
2536 r[dst] = result;
2537 ++vPC;
2538 NEXT_OPCODE;
2539 }
2540 BEGIN_OPCODE(op_put_by_val) {
2541 /* put_by_val base(r) property(r) value(r)
2542
2543 Sets register value on register base as the property named
2544 by register property. Base is converted to object
2545 first. register property is nominally converted to string
2546 but numbers are treated more efficiently.
2547
2548 Unlike many opcodes, this one does not write any output to
2549 the register file.
2550 */
2551 int base = (++vPC)->u.operand;
2552 int property = (++vPC)->u.operand;
2553 int value = (++vPC)->u.operand;
2554
2555 JSValue* baseValue = r[base].jsValue(exec);
2556 JSValue* subscript = r[property].jsValue(exec);
2557
2558 unsigned i;
2559
2560 bool isUInt32 = JSImmediate::getUInt32(subscript, i);
2561 if (LIKELY(isUInt32)) {
2562 if (isJSArray(baseValue)) {
2563 JSArray* jsArray = static_cast<JSArray*>(baseValue);
2564 if (jsArray->canSetIndex(i))
2565 jsArray->setIndex(i, r[value].jsValue(exec));
2566 else
2567 jsArray->JSArray::put(exec, i, r[value].jsValue(exec));
2568 } else
2569 baseValue->put(exec, i, r[value].jsValue(exec));
2570 } else {
2571 Identifier property(exec, subscript->toString(exec));
2572 if (!exec->hadException()) { // Don't put to an object if toString threw an exception.
2573 PutPropertySlot slot;
2574 baseValue->put(exec, property, r[value].jsValue(exec), slot);
2575 }
2576 }
2577
2578 VM_CHECK_EXCEPTION();
2579 ++vPC;
2580 NEXT_OPCODE;
2581 }
2582 BEGIN_OPCODE(op_del_by_val) {
2583 /* del_by_val dst(r) base(r) property(r)
2584
2585 Converts register base to Object, deletes the property
2586 named by register property from the object, and writes a
2587 boolean indicating success (if true) or failure (if false)
2588 to register dst.
2589 */
2590 int dst = (++vPC)->u.operand;
2591 int base = (++vPC)->u.operand;
2592 int property = (++vPC)->u.operand;
2593
2594 JSObject* baseObj = r[base].jsValue(exec)->toObject(exec); // may throw
2595
2596 JSValue* subscript = r[property].jsValue(exec);
2597 JSValue* result;
2598 uint32_t i;
2599 if (subscript->getUInt32(i))
2600 result = jsBoolean(baseObj->deleteProperty(exec, i));
2601 else {
2602 VM_CHECK_EXCEPTION();
2603 Identifier property(exec, subscript->toString(exec));
2604 VM_CHECK_EXCEPTION();
2605 result = jsBoolean(baseObj->deleteProperty(exec, property));
2606 }
2607
2608 VM_CHECK_EXCEPTION();
2609 r[dst] = result;
2610 ++vPC;
2611 NEXT_OPCODE;
2612 }
2613 BEGIN_OPCODE(op_put_by_index) {
2614 /* put_by_index base(r) property(n) value(r)
2615
2616 Sets register value on register base as the property named
2617 by the immediate number property. Base is converted to
2618 object first.
2619
2620 Unlike many opcodes, this one does not write any output to
2621 the register file.
2622
2623 This opcode is mainly used to initialize array literals.
2624 */
2625 int base = (++vPC)->u.operand;
2626 unsigned property = (++vPC)->u.operand;
2627 int value = (++vPC)->u.operand;
2628
2629 r[base].jsValue(exec)->put(exec, property, r[value].jsValue(exec));
2630
2631 ++vPC;
2632 NEXT_OPCODE;
2633 }
2634 BEGIN_OPCODE(op_loop) {
2635 /* loop target(offset)
2636
2637 Jumps unconditionally to offset target from the current
2638 instruction.
2639
2640 Additionally this loop instruction may terminate JS execution is
2641 the JS timeout is reached.
2642 */
2643#if DUMP_OPCODE_STATS
2644 OpcodeStats::resetLastInstruction();
2645#endif
2646 int target = (++vPC)->u.operand;
2647 CHECK_FOR_TIMEOUT();
2648 vPC += target;
2649 NEXT_OPCODE;
2650 }
2651 BEGIN_OPCODE(op_jmp) {
2652 /* jmp target(offset)
2653
2654 Jumps unconditionally to offset target from the current
2655 instruction.
2656 */
2657#if DUMP_OPCODE_STATS
2658 OpcodeStats::resetLastInstruction();
2659#endif
2660 int target = (++vPC)->u.operand;
2661
2662 vPC += target;
2663 NEXT_OPCODE;
2664 }
2665 BEGIN_OPCODE(op_loop_if_true) {
2666 /* loop_if_true cond(r) target(offset)
2667
2668 Jumps to offset target from the current instruction, if and
2669 only if register cond converts to boolean as true.
2670
2671 Additionally this loop instruction may terminate JS execution is
2672 the JS timeout is reached.
2673 */
2674 int cond = (++vPC)->u.operand;
2675 int target = (++vPC)->u.operand;
2676 if (r[cond].jsValue(exec)->toBoolean(exec)) {
2677 vPC += target;
2678 CHECK_FOR_TIMEOUT();
2679 NEXT_OPCODE;
2680 }
2681
2682 ++vPC;
2683 NEXT_OPCODE;
2684 }
2685 BEGIN_OPCODE(op_jtrue) {
2686 /* jtrue cond(r) target(offset)
2687
2688 Jumps to offset target from the current instruction, if and
2689 only if register cond converts to boolean as true.
2690 */
2691 int cond = (++vPC)->u.operand;
2692 int target = (++vPC)->u.operand;
2693 if (r[cond].jsValue(exec)->toBoolean(exec)) {
2694 vPC += target;
2695 NEXT_OPCODE;
2696 }
2697
2698 ++vPC;
2699 NEXT_OPCODE;
2700 }
2701 BEGIN_OPCODE(op_jfalse) {
2702 /* jfalse cond(r) target(offset)
2703
2704 Jumps to offset target from the current instruction, if and
2705 only if register cond converts to boolean as false.
2706 */
2707 int cond = (++vPC)->u.operand;
2708 int target = (++vPC)->u.operand;
2709 if (!r[cond].jsValue(exec)->toBoolean(exec)) {
2710 vPC += target;
2711 NEXT_OPCODE;
2712 }
2713
2714 ++vPC;
2715 NEXT_OPCODE;
2716 }
2717 BEGIN_OPCODE(op_loop_if_less) {
2718 /* loop_if_less src1(r) src2(r) target(offset)
2719
2720 Checks whether register src1 is less than register src2, as
2721 with the ECMAScript '<' operator, and then jumps to offset
2722 target from the current instruction, if and only if the
2723 result of the comparison is true.
2724
2725 Additionally this loop instruction may terminate JS execution is
2726 the JS timeout is reached.
2727 */
2728 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2729 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2730 int target = (++vPC)->u.operand;
2731
2732 bool result = jsLess(exec, src1, src2);
2733 VM_CHECK_EXCEPTION();
2734
2735 if (result) {
2736 vPC += target;
2737 CHECK_FOR_TIMEOUT();
2738 NEXT_OPCODE;
2739 }
2740
2741 ++vPC;
2742 NEXT_OPCODE;
2743 }
2744 BEGIN_OPCODE(op_jnless) {
2745 /* jnless src1(r) src2(r) target(offset)
2746
2747 Checks whether register src1 is less than register src2, as
2748 with the ECMAScript '<' operator, and then jumps to offset
2749 target from the current instruction, if and only if the
2750 result of the comparison is false.
2751 */
2752 JSValue* src1 = r[(++vPC)->u.operand].jsValue(exec);
2753 JSValue* src2 = r[(++vPC)->u.operand].jsValue(exec);
2754 int target = (++vPC)->u.operand;
2755
2756 bool result = jsLess(exec, src1, src2);
2757 VM_CHECK_EXCEPTION();
2758
2759 if (!result) {
2760 vPC += target;
2761 NEXT_OPCODE;
2762 }
2763
2764 ++vPC;
2765 NEXT_OPCODE;
2766 }
2767 BEGIN_OPCODE(op_switch_imm) {
2768 /* switch_imm tableIndex(n) defaultOffset(offset) scrutinee(r)
2769
2770 Performs a range checked switch on the scrutinee value, using
2771 the tableIndex-th immediate switch jump table. If the scrutinee value
2772 is an immediate number in the range covered by the referenced jump
2773 table, and the value at jumpTable[scrutinee value] is non-zero, then
2774 that value is used as the jump offset, otherwise defaultOffset is used.
2775 */
2776 int tableIndex = (++vPC)->u.operand;
2777 int defaultOffset = (++vPC)->u.operand;
2778 JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2779 if (!JSImmediate::isNumber(scrutinee))
2780 vPC += defaultOffset;
2781 else {
2782 int32_t value = JSImmediate::getTruncatedInt32(scrutinee);
2783 vPC += codeBlock->immediateSwitchJumpTables[tableIndex].offsetForValue(value, defaultOffset);
2784 }
2785 NEXT_OPCODE;
2786 }
2787 BEGIN_OPCODE(op_switch_char) {
2788 /* switch_char tableIndex(n) defaultOffset(offset) scrutinee(r)
2789
2790 Performs a range checked switch on the scrutinee value, using
2791 the tableIndex-th character switch jump table. If the scrutinee value
2792 is a single character string in the range covered by the referenced jump
2793 table, and the value at jumpTable[scrutinee value] is non-zero, then
2794 that value is used as the jump offset, otherwise defaultOffset is used.
2795 */
2796 int tableIndex = (++vPC)->u.operand;
2797 int defaultOffset = (++vPC)->u.operand;
2798 JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2799 if (!scrutinee->isString())
2800 vPC += defaultOffset;
2801 else {
2802 UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
2803 if (value->size() != 1)
2804 vPC += defaultOffset;
2805 else
2806 vPC += codeBlock->characterSwitchJumpTables[tableIndex].offsetForValue(value->data()[0], defaultOffset);
2807 }
2808 NEXT_OPCODE;
2809 }
2810 BEGIN_OPCODE(op_switch_string) {
2811 /* switch_string tableIndex(n) defaultOffset(offset) scrutinee(r)
2812
2813 Performs a sparse hashmap based switch on the value in the scrutinee
2814 register, using the tableIndex-th string switch jump table. If the
2815 scrutinee value is a string that exists as a key in the referenced
2816 jump table, then the value associated with the string is used as the
2817 jump offset, otherwise defaultOffset is used.
2818 */
2819 int tableIndex = (++vPC)->u.operand;
2820 int defaultOffset = (++vPC)->u.operand;
2821 JSValue* scrutinee = r[(++vPC)->u.operand].jsValue(exec);
2822 if (!scrutinee->isString())
2823 vPC += defaultOffset;
2824 else
2825 vPC += codeBlock->stringSwitchJumpTables[tableIndex].offsetForValue(static_cast<JSString*>(scrutinee)->value().rep(), defaultOffset);
2826 NEXT_OPCODE;
2827 }
2828 BEGIN_OPCODE(op_new_func) {
2829 /* new_func dst(r) func(f)
2830
2831 Constructs a new Function instance from function func and
2832 the current scope chain using the original Function
2833 constructor, using the rules for function declarations, and
2834 puts the result in register dst.
2835 */
2836 int dst = (++vPC)->u.operand;
2837 int func = (++vPC)->u.operand;
2838
2839 r[dst] = codeBlock->functions[func]->makeFunction(exec, scopeChain);
2840
2841 ++vPC;
2842 NEXT_OPCODE;
2843 }
2844 BEGIN_OPCODE(op_new_func_exp) {
2845 /* new_func_exp dst(r) func(f)
2846
2847 Constructs a new Function instance from function func and
2848 the current scope chain using the original Function
2849 constructor, using the rules for function expressions, and
2850 puts the result in register dst.
2851 */
2852 int dst = (++vPC)->u.operand;
2853 int func = (++vPC)->u.operand;
2854
2855 r[dst] = codeBlock->functionExpressions[func]->makeFunction(exec, scopeChain);
2856
2857 ++vPC;
2858 NEXT_OPCODE;
2859 }
2860 BEGIN_OPCODE(op_call_eval) {
2861 /* call_eval dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
2862
2863 Call a function named "eval" with no explicit "this" value
2864 (which may therefore be the eval operator). If register
2865 thisVal is the global object, and register func contains
2866 that global object's original global eval function, then
2867 perform the eval operator in local scope (interpreting
2868 the argument registers as for the "call"
2869 opcode). Otherwise, act exactly as the "call" opcode would.
2870 */
2871
2872 int dst = (++vPC)->u.operand;
2873 int func = (++vPC)->u.operand;
2874 int thisVal = (++vPC)->u.operand;
2875 int firstArg = (++vPC)->u.operand;
2876 int argCount = (++vPC)->u.operand;
2877
2878 JSValue* funcVal = r[func].jsValue(exec);
2879 JSValue* baseVal = r[thisVal].jsValue(exec);
2880
2881 if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
2882 JSObject* thisObject = static_cast<JSObject*>(r[codeBlock->thisRegister].jsValue(exec));
2883 JSValue* result = callEval(exec, thisObject, scopeChain, registerFile, r, firstArg, argCount, exceptionValue);
2884 if (exceptionValue)
2885 goto vm_throw;
2886
2887 r[dst] = result;
2888
2889 ++vPC;
2890 NEXT_OPCODE;
2891 }
2892
2893 // We didn't find the blessed version of eval, so reset vPC and process
2894 // this instruction as a normal function call, supplying the proper 'this'
2895 // value.
2896 vPC -= 5;
2897 r[thisVal] = baseVal->toThisObject(exec);
2898
2899#if HAVE(COMPUTED_GOTO)
2900 // Hack around gcc performance quirk by performing an indirect goto
2901 // in order to set the vPC -- attempting to do so directly results in a
2902 // significant regression.
2903 goto *op_call_indirect; // indirect goto -> op_call
2904#endif
2905 // fall through to op_call
2906 }
2907 BEGIN_OPCODE(op_call) {
2908 /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
2909
2910 Perform a function call. Specifically, call register func
2911 with a "this" value of register thisVal, and put the result
2912 in register dst.
2913
2914 The arguments start at register firstArg and go up to
2915 argCount, but the "this" value is considered an implicit
2916 first argument, so the argCount should be one greater than
2917 the number of explicit arguments passed, and the register
2918 after firstArg should contain the actual first
2919 argument. This opcode will copy from the thisVal register
2920 to the firstArg register, unless the register index of
2921 thisVal is the special missing this object marker, which is
2922 2^31-1; in that case, the global object will be used as the
2923 "this" value.
2924
2925 If func is a native code function, then this opcode calls
2926 it and returns the value immediately.
2927
2928 But if it is a JS function, then the current scope chain
2929 and code block is set to the function's, and we slide the
2930 register window so that the arguments would form the first
2931 few local registers of the called function's register
2932 window. In addition, a call frame header is written
2933 immediately before the arguments; see the call frame
2934 documentation for an explanation of how many registers a
2935 call frame takes and what they contain. That many registers
2936 before the firstArg register will be overwritten by the
2937 call. In addition, any registers higher than firstArg +
2938 argCount may be overwritten. Once this setup is complete,
2939 execution continues from the called function's first
2940 argument, and does not return until a "ret" opcode is
2941 encountered.
2942 */
2943
2944 int dst = (++vPC)->u.operand;
2945 int func = (++vPC)->u.operand;
2946 int thisVal = (++vPC)->u.operand;
2947 int firstArg = (++vPC)->u.operand;
2948 int argCount = (++vPC)->u.operand;
2949
2950 JSValue* v = r[func].jsValue(exec);
2951
2952 CallData callData;
2953 CallType callType = v->getCallData(callData);
2954
2955 if (*enabledProfilerReference)
2956 (*enabledProfilerReference)->willExecute(exec, static_cast<JSObject*>(v));
2957
2958 Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
2959 initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, 0, v);
2960 exec->m_callFrame = callFrame;
2961
2962 if (callType == CallTypeJS) {
2963
2964 ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
2965 FunctionBodyNode* functionBodyNode = callData.js.functionBody;
2966 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
2967
2968 r[firstArg] = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
2969
2970 r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
2971 if (UNLIKELY(exceptionValue != 0))
2972 goto vm_throw;
2973
2974 codeBlock = newCodeBlock;
2975 setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
2976 vPC = codeBlock->instructions.begin();
2977
2978#if DUMP_OPCODE_STATS
2979 OpcodeStats::resetLastInstruction();
2980#endif
2981
2982 NEXT_OPCODE;
2983 }
2984
2985 if (callType == CallTypeHost) {
2986 JSValue* thisValue = thisVal == missingThisObjectMarker() ? exec->globalThisValue() : r[thisVal].jsValue(exec);
2987 ArgList args(r + firstArg + 1, argCount - 1);
2988
2989 MACHINE_SAMPLING_callingHostFunction();
2990
2991 JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(v), thisValue, args);
2992 exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
2993 VM_CHECK_EXCEPTION();
2994
2995 r[dst] = returnValue;
2996
2997 if (*enabledProfilerReference)
2998 (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(v));
2999
3000 ++vPC;
3001 NEXT_OPCODE;
3002 }
3003
3004 ASSERT(callType == CallTypeNone);
3005
3006 exceptionValue = createNotAFunctionError(exec, v, vPC, codeBlock);
3007 exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3008 goto vm_throw;
3009 }
3010 BEGIN_OPCODE(op_ret) {
3011 /* ret result(r)
3012
3013 Return register result as the return value of the current
3014 function call, writing it into the caller's expected return
3015 value register. In addition, unwind one call frame and
3016 restore the scope chain, code block instruction pointer and
3017 register base to those of the calling function.
3018 */
3019
3020 int result = (++vPC)->u.operand;
3021
3022 Register* callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3023 if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
3024 ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
3025 ASSERT(activation->isActivationObject());
3026 activation->copyRegisters();
3027 }
3028
3029 if (*enabledProfilerReference)
3030 (*enabledProfilerReference)->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
3031
3032 if (codeBlock->needsFullScopeChain)
3033 scopeChain->deref();
3034
3035 JSValue* returnValue = r[result].jsValue(exec);
3036 if (callFrame[RegisterFile::CalledAsConstructor].i() && !returnValue->isObject()) {
3037 JSValue* thisObject = callFrame[RegisterFile::CallFrameHeaderSize].jsValue(exec);
3038 returnValue = thisObject;
3039 }
3040
3041 codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
3042 if (!codeBlock)
3043 return returnValue;
3044
3045 vPC = callFrame[RegisterFile::ReturnVPC].vPC();
3046 setScopeChain(exec, scopeChain, callFrame[RegisterFile::CallerScopeChain].scopeChain());
3047 r = callFrame[RegisterFile::CallerRegisters].r();
3048 exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3049 int dst = callFrame[RegisterFile::ReturnValueRegister].i();
3050 r[dst] = returnValue;
3051
3052 NEXT_OPCODE;
3053 }
3054 BEGIN_OPCODE(op_construct) {
3055 /* construct dst(r) constr(r) firstArg(r) argCount(n)
3056
3057 Invoke register "constr" as a constructor. For JS
3058 functions, the calling convention is exactly as for the
3059 "call" opcode, except that the "this" value is a newly
3060 created Object. For native constructors, a null "this"
3061 value is passed. In either case, the firstArg and argCount
3062 registers are interpreted as for the "call" opcode.
3063 */
3064
3065 int dst = (++vPC)->u.operand;
3066 int constr = (++vPC)->u.operand;
3067 int firstArg = (++vPC)->u.operand;
3068 int argCount = (++vPC)->u.operand;
3069
3070 JSValue* constrVal = r[constr].jsValue(exec);
3071
3072 ConstructData constructData;
3073 ConstructType constructType = constrVal->getConstructData(constructData);
3074
3075 // Removing this line of code causes a measurable regression on squirrelfish.
3076 JSObject* constructor = static_cast<JSObject*>(constrVal);
3077
3078 if (constructType == ConstructTypeJS) {
3079 if (*enabledProfilerReference)
3080 (*enabledProfilerReference)->willExecute(exec, constructor);
3081
3082 JSObject* prototype;
3083 JSValue* p = constructor->get(exec, exec->propertyNames().prototype);
3084 if (p->isObject())
3085 prototype = static_cast<JSObject*>(p);
3086 else
3087 prototype = scopeChain->globalObject()->objectPrototype();
3088 JSObject* newObject = new (exec) JSObject(prototype);
3089
3090 ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
3091 FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
3092 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
3093
3094 r[firstArg] = newObject; // "this" value
3095
3096 Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
3097 initializeCallFrame(callFrame, codeBlock, vPC, scopeChain, r, dst, firstArg, argCount, 1, constructor);
3098 exec->m_callFrame = callFrame;
3099
3100 r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
3101 if (exceptionValue)
3102 goto vm_throw;
3103
3104 codeBlock = newCodeBlock;
3105 setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
3106 vPC = codeBlock->instructions.begin();
3107
3108 NEXT_OPCODE;
3109 }
3110
3111 if (constructType == ConstructTypeHost) {
3112 if (*enabledProfilerReference)
3113 (*enabledProfilerReference)->willExecute(exec, constructor);
3114
3115 ArgList args(r + firstArg + 1, argCount - 1);
3116
3117 MACHINE_SAMPLING_callingHostFunction();
3118
3119 JSValue* returnValue = constructData.native.function(exec, constructor, args);
3120
3121 VM_CHECK_EXCEPTION();
3122 r[dst] = returnValue;
3123
3124 if (*enabledProfilerReference)
3125 (*enabledProfilerReference)->didExecute(exec, constructor);
3126
3127 ++vPC;
3128 NEXT_OPCODE;
3129 }
3130
3131 ASSERT(constructType == ConstructTypeNone);
3132
3133 exceptionValue = createNotAConstructorError(exec, constrVal, vPC, codeBlock);
3134 goto vm_throw;
3135 }
3136 BEGIN_OPCODE(op_push_scope) {
3137 /* push_scope scope(r)
3138
3139 Converts register scope to object, and pushes it onto the top
3140 of the current scope chain.
3141 */
3142 int scope = (++vPC)->u.operand;
3143 JSValue* v = r[scope].jsValue(exec);
3144 JSObject* o = v->toObject(exec);
3145 VM_CHECK_EXCEPTION();
3146
3147 setScopeChain(exec, scopeChain, scopeChain->push(o));
3148
3149 ++vPC;
3150 NEXT_OPCODE;
3151 }
3152 BEGIN_OPCODE(op_pop_scope) {
3153 /* pop_scope
3154
3155 Removes the top item from the current scope chain.
3156 */
3157 setScopeChain(exec, scopeChain, scopeChain->pop());
3158
3159 ++vPC;
3160 NEXT_OPCODE;
3161 }
3162 BEGIN_OPCODE(op_get_pnames) {
3163 /* get_pnames dst(r) base(r)
3164
3165 Creates a property name list for register base and puts it
3166 in register dst. This is not a true JavaScript value, just
3167 a synthetic value used to keep the iteration state in a
3168 register.
3169 */
3170 int dst = (++vPC)->u.operand;
3171 int base = (++vPC)->u.operand;
3172
3173 r[dst] = JSPropertyNameIterator::create(exec, r[base].jsValue(exec));
3174 ++vPC;
3175 NEXT_OPCODE;
3176 }
3177 BEGIN_OPCODE(op_next_pname) {
3178 /* next_pname dst(r) iter(r) target(offset)
3179
3180 Tries to copies the next name from property name list in
3181 register iter. If there are names left, then copies one to
3182 register dst, and jumps to offset target. If there are none
3183 left, invalidates the iterator and continues to the next
3184 instruction.
3185 */
3186 int dst = (++vPC)->u.operand;
3187 int iter = (++vPC)->u.operand;
3188 int target = (++vPC)->u.operand;
3189
3190 JSPropertyNameIterator* it = r[iter].jsPropertyNameIterator();
3191 if (JSValue* temp = it->next(exec)) {
3192 CHECK_FOR_TIMEOUT();
3193 r[dst] = temp;
3194 vPC += target;
3195 NEXT_OPCODE;
3196 }
3197 it->invalidate();
3198
3199 ++vPC;
3200 NEXT_OPCODE;
3201 }
3202 BEGIN_OPCODE(op_jmp_scopes) {
3203 /* jmp_scopes count(n) target(offset)
3204
3205 Removes the a number of items from the current scope chain
3206 specified by immediate number count, then jumps to offset
3207 target.
3208 */
3209 int count = (++vPC)->u.operand;
3210 int target = (++vPC)->u.operand;
3211
3212 ScopeChainNode* tmp = scopeChain;
3213 while (count--)
3214 tmp = tmp->pop();
3215 setScopeChain(exec, scopeChain, tmp);
3216
3217 vPC += target;
3218 NEXT_OPCODE;
3219 }
3220#if HAVE(COMPUTED_GOTO)
3221 // Appease GCC
3222 goto *(&&skip_new_scope);
3223#endif
3224 BEGIN_OPCODE(op_push_new_scope) {
3225 /* new_scope dst(r) property(id) value(r)
3226
3227 Constructs a new StaticScopeObject with property set to value. That scope
3228 object is then pushed onto the ScopeChain. The scope object is then stored
3229 in dst for GC.
3230 */
3231 setScopeChain(exec, scopeChain, createExceptionScope(exec, codeBlock, vPC, r, scopeChain));
3232 vPC += 4;
3233 NEXT_OPCODE;
3234 }
3235#if HAVE(COMPUTED_GOTO)
3236 skip_new_scope:
3237#endif
3238 BEGIN_OPCODE(op_catch) {
3239 /* catch ex(r)
3240
3241 Retrieves the VMs current exception and puts it in register
3242 ex. This is only valid after an exception has been raised,
3243 and usually forms the beginning of an exception handler.
3244 */
3245 ASSERT(exceptionValue);
3246 ASSERT(!exec->hadException());
3247 int ex = (++vPC)->u.operand;
3248 r[ex] = exceptionValue;
3249 exceptionValue = 0;
3250
3251 ++vPC;
3252 NEXT_OPCODE;
3253 }
3254 BEGIN_OPCODE(op_throw) {
3255 /* throw ex(r)
3256
3257 Throws register ex as an exception. This involves three
3258 steps: first, it is set as the current exception in the
3259 VM's internal state, then the stack is unwound until an
3260 exception handler or a native code boundary is found, and
3261 then control resumes at the exception handler if any or
3262 else the script returns control to the nearest native caller.
3263 */
3264
3265 int ex = (++vPC)->u.operand;
3266 exceptionValue = r[ex].jsValue(exec);
3267
3268 handlerVPC = throwException(exec, exceptionValue, vPC, codeBlock, scopeChain, r, true);
3269 if (!handlerVPC) {
3270 *exception = exceptionValue;
3271 return jsNull();
3272 }
3273
3274#if HAVE(COMPUTED_GOTO)
3275 // Hack around gcc performance quirk by performing an indirect goto
3276 // in order to set the vPC -- attempting to do so directly results in a
3277 // significant regression.
3278 goto *op_throw_end_indirect; // indirect goto -> op_throw_end
3279 }
3280 op_throw_end: {
3281#endif
3282
3283 vPC = handlerVPC;
3284 NEXT_OPCODE;
3285 }
3286 BEGIN_OPCODE(op_unexpected_load) {
3287 /* unexpected_load load dst(r) src(k)
3288
3289 Copies constant src to register dst.
3290 */
3291 int dst = (++vPC)->u.operand;
3292 int src = (++vPC)->u.operand;
3293 r[dst] = codeBlock->unexpectedConstants[src];
3294
3295 ++vPC;
3296 NEXT_OPCODE;
3297 }
3298 BEGIN_OPCODE(op_new_error) {
3299 /* new_error dst(r) type(n) message(k)
3300
3301 Constructs a new Error instance using the original
3302 constructor, using immediate number n as the type and
3303 constant message as the message string. The result is
3304 written to register dst.
3305 */
3306 int dst = (++vPC)->u.operand;
3307 int type = (++vPC)->u.operand;
3308 int message = (++vPC)->u.operand;
3309
3310 r[dst] = Error::create(exec, (ErrorType)type, codeBlock->unexpectedConstants[message]->toString(exec), codeBlock->lineNumberForVPC(vPC), codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->sourceURL());
3311
3312 ++vPC;
3313 NEXT_OPCODE;
3314 }
3315 BEGIN_OPCODE(op_end) {
3316 /* end result(r)
3317
3318 Return register result as the value of a global or eval
3319 program. Return control to the calling native code.
3320 */
3321
3322 if (codeBlock->needsFullScopeChain) {
3323 ASSERT(scopeChain->refCount > 1);
3324 scopeChain->deref();
3325 }
3326 int result = (++vPC)->u.operand;
3327 return r[result].jsValue(exec);
3328 }
3329 BEGIN_OPCODE(op_put_getter) {
3330 /* put_getter base(r) property(id) function(r)
3331
3332 Sets register function on register base as the getter named
3333 by identifier property. Base and function are assumed to be
3334 objects as this op should only be used for getters defined
3335 in object literal form.
3336
3337 Unlike many opcodes, this one does not write any output to
3338 the register file.
3339 */
3340 int base = (++vPC)->u.operand;
3341 int property = (++vPC)->u.operand;
3342 int function = (++vPC)->u.operand;
3343
3344 ASSERT(r[base].jsValue(exec)->isObject());
3345 JSObject* baseObj = static_cast<JSObject*>(r[base].jsValue(exec));
3346 Identifier& ident = codeBlock->identifiers[property];
3347 ASSERT(r[function].jsValue(exec)->isObject());
3348 baseObj->defineGetter(exec, ident, static_cast<JSObject*>(r[function].jsValue(exec)));
3349
3350 ++vPC;
3351 NEXT_OPCODE;
3352 }
3353 BEGIN_OPCODE(op_put_setter) {
3354 /* put_setter base(r) property(id) function(r)
3355
3356 Sets register function on register base as the setter named
3357 by identifier property. Base and function are assumed to be
3358 objects as this op should only be used for setters defined
3359 in object literal form.
3360
3361 Unlike many opcodes, this one does not write any output to
3362 the register file.
3363 */
3364 int base = (++vPC)->u.operand;
3365 int property = (++vPC)->u.operand;
3366 int function = (++vPC)->u.operand;
3367
3368 ASSERT(r[base].jsValue(exec)->isObject());
3369 JSObject* baseObj = static_cast<JSObject*>(r[base].jsValue(exec));
3370 Identifier& ident = codeBlock->identifiers[property];
3371 ASSERT(r[function].jsValue(exec)->isObject());
3372 baseObj->defineSetter(exec, ident, static_cast<JSObject*>(r[function].jsValue(exec)));
3373
3374 ++vPC;
3375 NEXT_OPCODE;
3376 }
3377 BEGIN_OPCODE(op_jsr) {
3378 /* jsr retAddrDst(r) target(offset)
3379
3380 Places the address of the next instruction into the retAddrDst
3381 register and jumps to offset target from the current instruction.
3382 */
3383 int retAddrDst = (++vPC)->u.operand;
3384 int target = (++vPC)->u.operand;
3385 r[retAddrDst] = vPC + 1;
3386
3387 vPC += target;
3388 NEXT_OPCODE;
3389 }
3390 BEGIN_OPCODE(op_sret) {
3391 /* sret retAddrSrc(r)
3392
3393 Jumps to the address stored in the retAddrSrc register. This
3394 differs from op_jmp because the target address is stored in a
3395 register, not as an immediate.
3396 */
3397 int retAddrSrc = (++vPC)->u.operand;
3398 vPC = r[retAddrSrc].vPC();
3399 NEXT_OPCODE;
3400 }
3401 BEGIN_OPCODE(op_debug) {
3402 /* debug debugHookID(n) firstLine(n) lastLine(n)
3403
3404 Notifies the debugger of the current state of execution. This opcode
3405 is only generated while the debugger is attached.
3406 */
3407 int debugHookID = (++vPC)->u.operand;
3408 int firstLine = (++vPC)->u.operand;
3409 int lastLine = (++vPC)->u.operand;
3410
3411 debug(exec, codeBlock, scopeChain, r, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
3412
3413 ++vPC;
3414 NEXT_OPCODE;
3415 }
3416 vm_throw: {
3417 exec->clearException();
3418 if (!tickCount) {
3419 // The exceptionValue is a lie! (GCC produces bad code for reasons I
3420 // cannot fathom if we don't assign to the exceptionValue before branching)
3421 exceptionValue = createInterruptedExecutionException(exec);
3422 }
3423 handlerVPC = throwException(exec, exceptionValue, vPC, codeBlock, scopeChain, r, false);
3424 if (!handlerVPC) {
3425 *exception = exceptionValue;
3426 return jsNull();
3427 }
3428 vPC = handlerVPC;
3429 NEXT_OPCODE;
3430 }
3431 }
3432 #undef NEXT_OPCODE
3433 #undef BEGIN_OPCODE
3434 #undef VM_CHECK_EXCEPTION
3435 #undef CHECK_FOR_TIMEOUT
3436}
3437
3438JSValue* Machine::retrieveArguments(ExecState* exec, JSFunction* function) const
3439{
3440 Register* callFrame = this->callFrame(exec, function);
3441 if (!callFrame)
3442 return jsNull();
3443
3444 JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec));
3445 if (!activation) {
3446 CodeBlock* codeBlock = &function->m_body->generatedByteCode();
3447 activation = new (exec) JSActivation(exec, function->m_body, callFrame + RegisterFile::CallFrameHeaderSize + codeBlock->numLocals);
3448 callFrame[RegisterFile::OptionalCalleeActivation] = activation;
3449 }
3450
3451 return activation->get(exec, exec->propertyNames().arguments);
3452}
3453
3454JSValue* Machine::retrieveCaller(ExecState* exec, InternalFunction* function) const
3455{
3456 Register* callFrame = this->callFrame(exec, function);
3457 if (!callFrame)
3458 return jsNull();
3459
3460 CodeBlock* callerCodeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
3461 if (!callerCodeBlock)
3462 return jsNull();
3463
3464 Register* callerCallFrame = callFrame[RegisterFile::CallerRegisters].r() - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3465 if (JSValue* caller = callerCallFrame[RegisterFile::Callee].jsValue(exec))
3466 return caller;
3467
3468 return jsNull();
3469}
3470
3471void Machine::retrieveLastCaller(ExecState* exec, int& lineNumber, int& sourceId, UString& sourceURL, JSValue*& function) const
3472{
3473 function = 0;
3474 lineNumber = -1;
3475 sourceURL = UString();
3476
3477 Register* callFrame = exec->m_callFrame;
3478 if (!callFrame)
3479 return;
3480
3481 CodeBlock* callerCodeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
3482 if (!callerCodeBlock)
3483 return;
3484
3485 Instruction* vPC = callFrame[RegisterFile::ReturnVPC].vPC();
3486 lineNumber = callerCodeBlock->lineNumberForVPC(vPC - 1);
3487 sourceId = callerCodeBlock->ownerNode->sourceId();
3488 sourceURL = callerCodeBlock->ownerNode->sourceURL();
3489
3490 JSValue* callee = callFrame[RegisterFile::Callee].getJSValue();
3491 if (callee->toThisObject(exec)->inherits(&InternalFunction::info))
3492 function = retrieveCaller(exec, static_cast<InternalFunction*>(callee));
3493}
3494
3495Register* Machine::callFrame(ExecState* exec, InternalFunction* function) const
3496{
3497 Register* callFrame = exec->m_callFrame;
3498
3499 while (1) {
3500 while (!callFrame) {
3501 exec = exec->m_prev;
3502 if (!exec)
3503 return 0;
3504 callFrame = exec->m_callFrame;
3505 }
3506
3507 if (callFrame[RegisterFile::Callee].jsValue(exec) == function)
3508 return callFrame;
3509
3510 CodeBlock* callerCodeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
3511 if (!callerCodeBlock) {
3512 callFrame = 0;
3513 continue;
3514 }
3515
3516 callFrame = callFrame[RegisterFile::CallerRegisters].r() - callerCodeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
3517 }
3518}
3519
3520void Machine::getArgumentsData(Register* callFrame, JSFunction*& function, Register*& argv, int& argc)
3521{
3522 function = static_cast<JSFunction*>(callFrame[RegisterFile::Callee].getJSValue());
3523 ASSERT(function->inherits(&JSFunction::info));
3524
3525 argv = callFrame[RegisterFile::CallerRegisters].r() + callFrame[RegisterFile::ArgumentStartRegister].i() + 1; // + 1 to skip "this"
3526 argc = callFrame[RegisterFile::ArgumentCount].i() - 1; // - 1 to skip "this"
3527}
3528
3529#if ENABLE(CTI)
3530
3531NEVER_INLINE static void doSetReturnAddressVMThrowTrampoline(void** returnAddress)
3532{
3533 ctiSetReturnAddress(returnAddress, (void*)ctiVMThrowTrampoline);
3534}
3535
3536NEVER_INLINE void Machine::tryCTICachePutByID(ExecState* exec, CodeBlock* codeBlock, void* returnAddress, JSValue* baseValue, const PutPropertySlot& slot)
3537{
3538 // The interpreter checks for recursion here; I do not believe this can occur in CTI.
3539
3540 if (JSImmediate::isImmediate(baseValue))
3541 return;
3542
3543 // Uncacheable: give up.
3544 if (!slot.isCacheable()) {
3545 ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
3546 return;
3547 }
3548
3549 // FIXME: Cache new property transitions, too.
3550 if (slot.type() == PutPropertySlot::NewProperty) {
3551 ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
3552 return;
3553 }
3554
3555 JSCell* baseCell = static_cast<JSCell*>(baseValue);
3556 StructureID* structureID = baseCell->structureID();
3557
3558 // FIXME: Remove this !structureID check once all objects have StructureIDs.
3559 if (!structureID) {
3560 ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
3561 return;
3562 }
3563
3564 if (structureID->isDictionary()) {
3565 ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
3566 return;
3567 }
3568
3569 // In the interpreter the last structure is trapped here; in CTI we use the
3570 // *_second method to achieve a similar (but not quite the same) effect.
3571
3572 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(returnAddress);
3573 Instruction* vPC = codeBlock->instructions.begin() + vPCIndex;
3574
3575 // Cache hit: Specialize instruction and ref StructureIDs.
3576
3577 // If baseCell != base, then baseCell must be a proxy for another object.
3578 if (baseCell != slot.base()) {
3579 ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_put_by_id_generic);
3580 return;
3581 }
3582 vPC[0] = getOpcode(op_put_by_id_replace);
3583 vPC[4] = structureID;
3584 vPC[5] = slot.cachedOffset();
3585 codeBlock->refStructureIDs(vPC);
3586
3587 ctiRepatchCallByReturnAddress(returnAddress, CTI::compilePutByIdReplace(this, exec, codeBlock, structureID, slot.cachedOffset()));
3588}
3589
3590void* Machine::getCTIArrayLengthTrampoline(ExecState* exec, CodeBlock* codeBlock)
3591{
3592 if (!m_ctiArrayLengthTrampoline)
3593 m_ctiArrayLengthTrampoline = CTI::compileArrayLengthTrampoline(this, exec, codeBlock);
3594
3595 return m_ctiArrayLengthTrampoline;
3596}
3597
3598void* Machine::getCTIStringLengthTrampoline(ExecState* exec, CodeBlock* codeBlock)
3599{
3600 if (!m_ctiStringLengthTrampoline)
3601 m_ctiStringLengthTrampoline = CTI::compileStringLengthTrampoline(this, exec, codeBlock);
3602
3603 return m_ctiStringLengthTrampoline;
3604}
3605
3606NEVER_INLINE void Machine::tryCTICacheGetByID(ExecState* exec, CodeBlock* codeBlock, void* returnAddress, JSValue* baseValue, const Identifier& propertyName, const PropertySlot& slot)
3607{
3608 // The interpreter checks for recursion here; I do not believe this can occur in CTI.
3609
3610 if (isJSArray(baseValue) && propertyName == exec->propertyNames().length) {
3611 ctiRepatchCallByReturnAddress(returnAddress, getCTIArrayLengthTrampoline(exec, codeBlock));
3612 return;
3613 }
3614 if (isJSString(baseValue) && propertyName == exec->propertyNames().length) {
3615 ctiRepatchCallByReturnAddress(returnAddress, getCTIStringLengthTrampoline(exec, codeBlock));
3616 return;
3617 }
3618
3619 // Uncacheable: give up.
3620 if (!slot.isCacheable()) {
3621 ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
3622 return;
3623 }
3624
3625 // FIXME: Cache property access for immediates.
3626 if (JSImmediate::isImmediate(baseValue)) {
3627 ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
3628 return;
3629 }
3630
3631 JSCell* baseCell = static_cast<JSCell*>(baseValue);
3632 StructureID* structureID = baseCell->structureID();
3633
3634 // FIXME: Remove this !structureID check once all JSCells have StructureIDs.
3635 if (!structureID) {
3636 ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
3637 return;
3638 }
3639
3640 if (structureID->isDictionary()) {
3641 ctiRepatchCallByReturnAddress(returnAddress, (void*)cti_op_get_by_id_generic);
3642 return;
3643 }
3644
3645 // In the interpreter the last structure is trapped here; in CTI we use the
3646 // *_second method to achieve a similar (but not quite the same) effect.
3647
3648 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(returnAddress);
3649 Instruction* vPC = codeBlock->instructions.begin() + vPCIndex;
3650
3651 // Cache hit: Specialize instruction and ref StructureIDs.
3652
3653 if (slot.slotBase() == baseValue) {
3654 // set this up, so derefStructureIDs can do it's job.
3655 vPC[0] = getOpcode(op_get_by_id_self);
3656 vPC[4] = structureID;
3657 vPC[5] = slot.cachedOffset();
3658 codeBlock->refStructureIDs(vPC);
3659
3660 ctiRepatchCallByReturnAddress(returnAddress, CTI::compileGetByIdSelf(this, exec, codeBlock, structureID, slot.cachedOffset()));
3661 return;
3662 }
3663
3664 if (slot.slotBase() == structureID->prototype()) {
3665 ASSERT(slot.slotBase()->isObject());
3666
3667 JSObject* slotBaseObject = static_cast<JSObject*>(slot.slotBase());
3668
3669 // Heavy access to a prototype is a good indication that it's not being
3670 // used as a dictionary.
3671 if (slotBaseObject->structureID()->isDictionary()) {
3672 RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(slotBaseObject->structureID());
3673 slotBaseObject->setStructureID(transition.release());
3674 static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
3675 }
3676
3677 vPC[0] = getOpcode(op_get_by_id_proto);
3678 vPC[4] = structureID;
3679 vPC[5] = slotBaseObject->structureID();
3680 vPC[6] = slot.cachedOffset();
3681 codeBlock->refStructureIDs(vPC);
3682
3683 ctiRepatchCallByReturnAddress(returnAddress, CTI::compileGetByIdProto(this, exec, codeBlock, structureID, slotBaseObject->structureID(), slot.cachedOffset()));
3684 return;
3685 }
3686
3687 size_t count = 0;
3688 JSObject* o = static_cast<JSObject*>(baseValue);
3689 while (slot.slotBase() != o) {
3690 JSValue* v = o->structureID()->prototype();
3691
3692 // If we didn't find slotBase in baseValue's prototype chain, then baseValue
3693 // must be a proxy for another object.
3694
3695 if (v->isNull()) {
3696 vPC[0] = getOpcode(op_get_by_id_generic);
3697 return;
3698 }
3699
3700 o = static_cast<JSObject*>(v);
3701
3702 // Heavy access to a prototype is a good indication that it's not being
3703 // used as a dictionary.
3704 if (o->structureID()->isDictionary()) {
3705 RefPtr<StructureID> transition = StructureID::fromDictionaryTransition(o->structureID());
3706 o->setStructureID(transition.release());
3707 static_cast<JSObject*>(baseValue)->structureID()->setCachedPrototypeChain(0);
3708 }
3709
3710 ++count;
3711 }
3712
3713 StructureIDChain* chain = structureID->cachedPrototypeChain();
3714 if (!chain)
3715 chain = cachePrototypeChain(structureID);
3716
3717 vPC[0] = getOpcode(op_get_by_id_chain);
3718 vPC[4] = structureID;
3719 vPC[5] = chain;
3720 vPC[6] = count;
3721 vPC[7] = slot.cachedOffset();
3722 codeBlock->refStructureIDs(vPC);
3723
3724 ctiRepatchCallByReturnAddress(returnAddress, CTI::compileGetByIdChain(this, exec, codeBlock, structureID, chain, count, slot.cachedOffset()));
3725}
3726
3727
3728#define JSVALUE_VM_CHECK_EXCEPTION_ARG(exception) \
3729 do { \
3730 if (UNLIKELY(exception != 0)) { \
3731 exec->setException(exception); \
3732 exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
3733 doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
3734 return 0; \
3735 } \
3736 } while (0)
3737#define VM_CHECK_EXCEPTION_v() \
3738 do { \
3739 if (UNLIKELY(exec->hadException())) { \
3740 exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
3741 doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
3742 return; \
3743 } \
3744 } while (0)
3745#define VM_CHECK_EXCEPTION(type) \
3746 do { \
3747 if (UNLIKELY(exec->hadException())) { \
3748 exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
3749 doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
3750 return (type)0; \
3751 } \
3752 } while (0)
3753#define VM_CHECK_EXCEPTION_AT_END() \
3754 do { \
3755 if (UNLIKELY(exec->hadException())) { \
3756 /*printf("VM_CHECK_EXCEPTION_AT_END()\n");*/ \
3757 exec->setCTIReturnAddress(CTI_RETURN_ADDRESS); \
3758 doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS); \
3759 } \
3760 } while (0)
3761
3762void Machine::cti_op_end(CTI_ARGS)
3763{
3764 ASSERT(ARG_scopeChain->refCount > 1);
3765 ARG_scopeChain->deref();
3766}
3767
3768JSValue* Machine::cti_op_add(CTI_ARGS)
3769{
3770 JSValue* src1 = ARG_src1;
3771 JSValue* src2 = ARG_src2;
3772
3773 ExecState* exec = ARG_exec;
3774 JSValue* result = jsAdd(exec, src1, src2);
3775 VM_CHECK_EXCEPTION_AT_END();
3776 return result;
3777}
3778
3779JSValue* Machine::cti_op_pre_inc(CTI_ARGS)
3780{
3781 JSValue* v = ARG_src1;
3782
3783 ExecState* exec = ARG_exec;
3784 JSValue* result = jsNumber(exec, v->toNumber(exec) + 1);
3785 VM_CHECK_EXCEPTION_AT_END();
3786 return result;
3787}
3788
3789void Machine::cti_timeout_check(CTI_ARGS)
3790{
3791 ExecState* exec = ARG_exec;
3792
3793 if (exec->machine()->checkTimeout(exec->dynamicGlobalObject()))
3794 exec->setException(createInterruptedExecutionException(exec));
3795
3796 VM_CHECK_EXCEPTION_AT_END();
3797}
3798
3799
3800int Machine::cti_op_loop_if_less(CTI_ARGS)
3801{
3802 JSValue* src1 = ARG_src1;
3803 JSValue* src2 = ARG_src2;
3804 ExecState* exec = ARG_exec;
3805
3806 bool result = jsLess(exec, src1, src2);
3807 VM_CHECK_EXCEPTION_AT_END();
3808 return result;
3809}
3810
3811JSValue* Machine::cti_op_new_object(CTI_ARGS)
3812{
3813 return constructEmptyObject(ARG_exec);;
3814}
3815
3816void Machine::cti_op_put_by_id(CTI_ARGS)
3817{
3818 ExecState* exec = ARG_exec;
3819 Identifier& ident = *ARG_id2;
3820
3821 PutPropertySlot slot;
3822 ARG_src1->put(exec, ident, ARG_src3, slot);
3823
3824 ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_put_by_id_second);
3825
3826 VM_CHECK_EXCEPTION_AT_END();
3827}
3828
3829void Machine::cti_op_put_by_id_second(CTI_ARGS)
3830{
3831 ExecState* exec = ARG_exec;
3832 Identifier& ident = *ARG_id2;
3833
3834 JSValue* baseValue = ARG_src1;
3835 PutPropertySlot slot;
3836 baseValue->put(exec, ident, ARG_src3, slot);
3837
3838 exec->machine()->tryCTICachePutByID(exec, ARG_codeBlock, CTI_RETURN_ADDRESS, baseValue, slot);
3839
3840 VM_CHECK_EXCEPTION_AT_END();
3841}
3842
3843void Machine::cti_op_put_by_id_generic(CTI_ARGS)
3844{
3845 ExecState* exec = ARG_exec;
3846 Identifier& ident = *ARG_id2;
3847
3848 PutPropertySlot slot;
3849 ARG_src1->put(exec, ident, ARG_src3, slot);
3850
3851 VM_CHECK_EXCEPTION_AT_END();
3852}
3853
3854void Machine::cti_op_put_by_id_fail(CTI_ARGS)
3855{
3856 ExecState* exec = ARG_exec;
3857 Identifier& ident = *ARG_id2;
3858
3859 PutPropertySlot slot;
3860 ARG_src1->put(exec, ident, ARG_src3, slot);
3861
3862 // should probably uncachePutByID() ... this would mean doing a vPC lookup - might be worth just bleeding this until the end.
3863 ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_put_by_id_generic);
3864
3865 VM_CHECK_EXCEPTION_AT_END();
3866}
3867
3868JSValue* Machine::cti_op_get_by_id(CTI_ARGS)
3869{
3870 ExecState* exec = ARG_exec;
3871 Identifier& ident = *ARG_id2;
3872
3873 JSValue* baseValue = ARG_src1;
3874 PropertySlot slot(baseValue);
3875 JSValue* result = baseValue->get(exec, ident, slot);
3876
3877 ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_get_by_id_second);
3878
3879 VM_CHECK_EXCEPTION_AT_END();
3880 return result;
3881}
3882
3883JSValue* Machine::cti_op_get_by_id_second(CTI_ARGS)
3884{
3885 ExecState* exec = ARG_exec;
3886 Identifier& ident = *ARG_id2;
3887
3888 JSValue* baseValue = ARG_src1;
3889 PropertySlot slot(baseValue);
3890 JSValue* result = baseValue->get(exec, ident, slot);
3891
3892 exec->machine()->tryCTICacheGetByID(exec, ARG_codeBlock, CTI_RETURN_ADDRESS, baseValue, ident, slot);
3893
3894 VM_CHECK_EXCEPTION_AT_END();
3895 return result;
3896}
3897
3898JSValue* Machine::cti_op_get_by_id_generic(CTI_ARGS)
3899{
3900 ExecState* exec = ARG_exec;
3901 Identifier& ident = *ARG_id2;
3902
3903 JSValue* baseValue = ARG_src1;
3904 PropertySlot slot(baseValue);
3905 JSValue* result = baseValue->get(exec, ident, slot);
3906
3907 VM_CHECK_EXCEPTION_AT_END();
3908 return result;
3909}
3910
3911JSValue* Machine::cti_op_get_by_id_fail(CTI_ARGS)
3912{
3913 ExecState* exec = ARG_exec;
3914 Identifier& ident = *ARG_id2;
3915
3916 JSValue* baseValue = ARG_src1;
3917 PropertySlot slot(baseValue);
3918 JSValue* result = baseValue->get(exec, ident, slot);
3919
3920 // should probably uncacheGetByID() ... this would mean doing a vPC lookup - might be worth just bleeding this until the end.
3921 ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, (void*)cti_op_get_by_id_generic);
3922
3923 VM_CHECK_EXCEPTION_AT_END();
3924 return result;
3925}
3926
3927JSValue* Machine::cti_op_instanceof(CTI_ARGS)
3928{
3929 ExecState* exec = ARG_exec;
3930 JSValue* baseVal = ARG_src2;
3931
3932 if (!baseVal->isObject()) {
3933 CodeBlock* codeBlock = ARG_codeBlock;
3934 ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
3935 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
3936 exec->setException(createInvalidParamError(exec, "instanceof", baseVal, codeBlock->instructions.begin() + vPCIndex, codeBlock));
3937 VM_CHECK_EXCEPTION(JSValue*);
3938 }
3939
3940 JSObject* baseObj = static_cast<JSObject*>(baseVal);
3941 JSValue* result = jsBoolean(baseObj->implementsHasInstance() ? baseObj->hasInstance(exec, ARG_src1) : false);
3942 VM_CHECK_EXCEPTION_AT_END();
3943 return result;
3944}
3945
3946JSValue* Machine::cti_op_del_by_id(CTI_ARGS)
3947{
3948 ExecState* exec = ARG_exec;
3949 Identifier& ident = *ARG_id2;
3950
3951 JSObject* baseObj = ARG_src1->toObject(exec);
3952
3953 JSValue* result = jsBoolean(baseObj->deleteProperty(exec, ident));
3954 VM_CHECK_EXCEPTION_AT_END();
3955 return result;
3956}
3957
3958JSValue* Machine::cti_op_mul(CTI_ARGS)
3959{
3960 ExecState* exec = ARG_exec;
3961 JSValue* src1 = ARG_src1;
3962 JSValue* src2 = ARG_src2;
3963
3964 double left;
3965 double right;
3966 if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
3967 return jsNumber(exec, left * right);
3968 else {
3969 JSValue* result = jsNumber(exec, src1->toNumber(exec) * src2->toNumber(exec));
3970 VM_CHECK_EXCEPTION_AT_END();
3971 return result;
3972 }
3973}
3974
3975JSValue* Machine::cti_op_new_func(CTI_ARGS)
3976{
3977 return ARG_func1->makeFunction(ARG_exec, ARG_scopeChain);
3978}
3979
3980void* Machine::cti_op_call_JSFunction(CTI_ARGS)
3981{
3982 ExecState* exec = ARG_exec;
3983 RegisterFile* registerFile = ARG_registerFile;
3984 Register* r = ARG_r;
3985 CodeBlock* codeBlock = ARG_codeBlock;
3986 ScopeChainNode* scopeChain = ARG_scopeChain;
3987
3988 Machine* machine = exec->machine();
3989 JSValue* exceptionValue = 0;
3990 Register* registerBase = registerFile->base();
3991
3992 JSValue* funcVal = ARG_src1;
3993 JSValue* thisValue = ARG_src2;
3994 int firstArg = ARG_int3;
3995 int argCount = ARG_int4;
3996
3997 CallData callData;
3998#ifndef NDEBUG
3999 CallType callType =
4000#endif
4001 funcVal->getCallData(callData);
4002
4003 ASSERT(callType == CallTypeJS);
4004
4005 if (*ARG_profilerReference)
4006 (*ARG_profilerReference)->willExecute(exec, static_cast<JSObject*>(funcVal));
4007
4008 ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
4009 FunctionBodyNode* functionBodyNode = callData.js.functionBody;
4010 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
4011
4012 r[firstArg] = thisValue;
4013
4014 Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
4015 machine->initializeCallFrame(callFrame, codeBlock, ARG_instr5, scopeChain, r, 0/*dst*/, firstArg, argCount, 0, funcVal);
4016 exec->m_callFrame = callFrame;
4017
4018 r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
4019 JSVALUE_VM_CHECK_EXCEPTION_ARG(exceptionValue);
4020
4021 codeBlock = newCodeBlock;
4022 machine->setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
4023
4024 if (!codeBlock->ctiCode)
4025 CTI::compile(machine, exec, codeBlock);
4026
4027 ARG_setScopeChain(scopeChain);
4028 ARG_setCodeBlock(codeBlock);
4029 ARG_setR(r);
4030 return codeBlock->ctiCode;
4031}
4032
4033JSValue* Machine::cti_op_call_NotJSFunction(CTI_ARGS)
4034{
4035 ExecState* exec = ARG_exec;
4036 Register* r = ARG_r;
4037
4038 JSValue* funcVal = ARG_src1;
4039 JSValue* thisValue = ARG_src2;
4040 int firstArg = ARG_int3;
4041 int argCount = ARG_int4;
4042
4043 CallData callData;
4044 CallType callType = funcVal->getCallData(callData);
4045
4046 ASSERT(callType != CallTypeJS);
4047
4048 if (callType == CallTypeHost) {
4049 CodeBlock* codeBlock = ARG_codeBlock;
4050 ScopeChainNode* scopeChain = ARG_scopeChain;
4051 Machine* machine = exec->machine();
4052
4053 Register* oldCallFrame = exec->m_callFrame;
4054 Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
4055 machine->initializeCallFrame(callFrame, codeBlock, ARG_instr5, scopeChain, r, 0/*dst*/, firstArg, argCount, 0, funcVal);
4056 exec->m_callFrame = callFrame;
4057
4058 if (*ARG_profilerReference)
4059 (*ARG_profilerReference)->willExecute(exec, static_cast<JSObject*>(funcVal));
4060
4061 ArgList argList(r + firstArg + 1, argCount - 1);
4062
4063 CTI_MACHINE_SAMPLING_callingHostFunction();
4064
4065 JSValue* returnValue = callData.native.function(exec, static_cast<JSObject*>(funcVal), thisValue, argList);
4066 exec->m_callFrame = oldCallFrame;
4067 VM_CHECK_EXCEPTION(JSValue*);
4068
4069 if (*ARG_profilerReference)
4070 (*ARG_profilerReference)->didExecute(exec, static_cast<JSObject*>(funcVal));
4071
4072 return returnValue;
4073
4074 }
4075
4076 ASSERT(callType == CallTypeNone);
4077
4078 exec->setException(createNotAFunctionError(exec, funcVal, ARG_instr5, ARG_codeBlock));
4079 VM_CHECK_EXCEPTION_AT_END();
4080 return 0;
4081}
4082
4083JSValue* Machine::cti_op_ret(CTI_ARGS)
4084{
4085 ExecState* exec = ARG_exec;
4086 Register* r = ARG_r;
4087 CodeBlock* codeBlock = ARG_codeBlock;
4088 ScopeChainNode* scopeChain = ARG_scopeChain;
4089
4090 Machine* machine = exec->machine();
4091
4092 Register* callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
4093 if (JSActivation* activation = static_cast<JSActivation*>(callFrame[RegisterFile::OptionalCalleeActivation].jsValue(exec))) {
4094 ASSERT(!codeBlock->needsFullScopeChain || scopeChain->object == activation);
4095 ASSERT(activation->isActivationObject());
4096 activation->copyRegisters();
4097 }
4098
4099 if (*ARG_profilerReference)
4100 (*ARG_profilerReference)->didExecute(exec, static_cast<JSObject*>(callFrame[RegisterFile::Callee].jsValue(exec)));
4101
4102 if (codeBlock->needsFullScopeChain)
4103 scopeChain->deref();
4104
4105 JSValue* returnValue = ARG_src1;
4106 if (callFrame[RegisterFile::CalledAsConstructor].i() && !returnValue->isObject()) {
4107 JSValue* thisObject = callFrame[RegisterFile::CallFrameHeaderSize].jsValue(exec);
4108 returnValue = thisObject;
4109 }
4110
4111 codeBlock = callFrame[RegisterFile::CallerCodeBlock].codeBlock();
4112 if (codeBlock) {
4113 machine->setScopeChain(exec, scopeChain, callFrame[RegisterFile::CallerScopeChain].scopeChain());
4114 r = callFrame[RegisterFile::CallerRegisters].r();
4115 exec->m_callFrame = r - codeBlock->numLocals - RegisterFile::CallFrameHeaderSize;
4116 }
4117
4118 ARG_setScopeChain(scopeChain);
4119 ARG_setCodeBlock(codeBlock);
4120 ARG_setR(r);
4121
4122 return returnValue;
4123}
4124
4125JSValue* Machine::cti_op_new_array(CTI_ARGS)
4126{
4127 ArgList argsList(ARG_registers1, ARG_int2);
4128 return constructArray(ARG_exec, argsList);
4129}
4130
4131JSValue* Machine::cti_op_resolve(CTI_ARGS)
4132{
4133 ExecState* exec = ARG_exec;
4134 ScopeChainNode* scopeChain = ARG_scopeChain;
4135
4136 ScopeChainIterator iter = scopeChain->begin();
4137 ScopeChainIterator end = scopeChain->end();
4138 ASSERT(iter != end);
4139
4140 Identifier& ident = *ARG_id1;
4141 do {
4142 JSObject* o = *iter;
4143 PropertySlot slot(o);
4144 if (o->getPropertySlot(exec, ident, slot)) {
4145 JSValue* result = slot.getValue(exec, ident);
4146 VM_CHECK_EXCEPTION_AT_END();
4147 return result;
4148 }
4149 } while (++iter != end);
4150
4151 CodeBlock* codeBlock = ARG_codeBlock;
4152 ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
4153 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
4154 exec->setException(createUndefinedVariableError(exec, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock));
4155
4156 VM_CHECK_EXCEPTION_AT_END();
4157 return 0;
4158}
4159
4160void* Machine::cti_op_construct_JSConstruct(CTI_ARGS)
4161{
4162 ExecState* exec = ARG_exec;
4163 RegisterFile* registerFile = ARG_registerFile;
4164 Register* r = ARG_r;
4165 CodeBlock* codeBlock = ARG_codeBlock;
4166 ScopeChainNode* scopeChain = ARG_scopeChain;
4167
4168 Machine* machine = exec->machine();
4169 JSValue* exceptionValue = 0;
4170 Register* registerBase = registerFile->base();
4171
4172 JSValue* constrVal = ARG_src1;
4173 int firstArg = ARG_int2;
4174 int argCount = ARG_int3;
4175
4176 ConstructData constructData;
4177#ifndef NDEBUG
4178 ConstructType constructType =
4179#endif
4180 constrVal->getConstructData(constructData);
4181
4182 // Removing this line of code causes a measurable regression on squirrelfish.
4183 JSObject* constructor = static_cast<JSObject*>(constrVal);
4184
4185 ASSERT(constructType == ConstructTypeJS);
4186
4187 if (*ARG_profilerReference)
4188 (*ARG_profilerReference)->willExecute(exec, constructor);
4189
4190 JSObject* prototype;
4191 JSValue* p = constructor->get(exec, exec->propertyNames().prototype);
4192 if (p->isObject())
4193 prototype = static_cast<JSObject*>(p);
4194 else
4195 prototype = scopeChain->globalObject()->objectPrototype();
4196 JSObject* newObject = new (exec) JSObject(prototype);
4197
4198 ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
4199 FunctionBodyNode* functionBodyNode = constructData.js.functionBody;
4200 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
4201
4202 r[firstArg] = newObject; // "this" value
4203
4204 Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
4205 machine->initializeCallFrame(callFrame, codeBlock, ARG_instr4, scopeChain, r, 0/*dst*/, firstArg, argCount, 1, constructor);
4206 exec->m_callFrame = callFrame;
4207
4208 r = slideRegisterWindowForCall(exec, newCodeBlock, registerFile, registerBase, r, firstArg, argCount, exceptionValue);
4209 JSVALUE_VM_CHECK_EXCEPTION_ARG(exceptionValue);
4210
4211 codeBlock = newCodeBlock;
4212 machine->setScopeChain(exec, scopeChain, scopeChainForCall(exec, functionBodyNode, codeBlock, callDataScopeChain, r));
4213
4214 if (!codeBlock->ctiCode)
4215 CTI::compile(machine, exec, codeBlock);
4216
4217 ARG_setScopeChain(scopeChain);
4218 ARG_setCodeBlock(codeBlock);
4219 ARG_setR(r);
4220 return codeBlock->ctiCode;
4221}
4222
4223JSValue* Machine::cti_op_construct_NotJSConstruct(CTI_ARGS)
4224{
4225 ExecState* exec = ARG_exec;
4226 Register* r = ARG_r;
4227
4228 JSValue* constrVal = ARG_src1;
4229 int firstArg = ARG_int2;
4230 int argCount = ARG_int3;
4231
4232 ConstructData constructData;
4233 ConstructType constructType = constrVal->getConstructData(constructData);
4234
4235 // Removing this line of code causes a measurable regression on squirrelfish.
4236 JSObject* constructor = static_cast<JSObject*>(constrVal);
4237
4238 ASSERT(constructType != ConstructTypeJS);
4239
4240 if (constructType == ConstructTypeHost) {
4241 CodeBlock* codeBlock = ARG_codeBlock;
4242 ScopeChainNode* scopeChain = ARG_scopeChain;
4243 Machine* machine = exec->machine();
4244
4245 Register* oldCallFrame = exec->m_callFrame;
4246 Register* callFrame = r + firstArg - RegisterFile::CallFrameHeaderSize;
4247 machine->initializeCallFrame(callFrame, codeBlock, ARG_instr5, scopeChain, r, 0/*dst*/, firstArg, argCount, 1, constrVal);
4248 exec->m_callFrame = callFrame;
4249
4250 if (*ARG_profilerReference)
4251 (*ARG_profilerReference)->willExecute(exec, constructor);
4252
4253 ArgList argList(r + firstArg + 1, argCount - 1);
4254
4255 CTI_MACHINE_SAMPLING_callingHostFunction();
4256
4257 JSValue* returnValue = constructData.native.function(exec, constructor, argList);
4258 exec->m_callFrame = oldCallFrame;
4259 VM_CHECK_EXCEPTION(JSValue*);
4260
4261 if (*ARG_profilerReference)
4262 (*ARG_profilerReference)->didExecute(exec, constructor);
4263
4264 return returnValue;
4265 }
4266
4267 ASSERT(constructType == ConstructTypeNone);
4268
4269 exec->setException(createNotAConstructorError(exec, constrVal, ARG_instr4, ARG_codeBlock));
4270 VM_CHECK_EXCEPTION_AT_END();
4271 return 0;
4272}
4273
4274JSValue* Machine::cti_op_get_by_val(CTI_ARGS)
4275{
4276 ExecState* exec = ARG_exec;
4277 Machine* machine = exec->machine();
4278
4279 JSValue* baseValue = ARG_src1;
4280 JSValue* subscript = ARG_src2;
4281
4282 JSValue* result;
4283 unsigned i;
4284
4285 bool isUInt32 = JSImmediate::getUInt32(subscript, i);
4286 if (LIKELY(isUInt32)) {
4287 if (machine->isJSArray(baseValue)) {
4288 JSArray* jsArray = static_cast<JSArray*>(baseValue);
4289 if (jsArray->canGetIndex(i))
4290 result = jsArray->getIndex(i);
4291 else
4292 result = jsArray->JSArray::get(exec, i);
4293 } else if (machine->isJSString(baseValue) && static_cast<JSString*>(baseValue)->canGetIndex(i))
4294 result = static_cast<JSString*>(baseValue)->getIndex(exec, i);
4295 else
4296 result = baseValue->get(exec, i);
4297 } else {
4298 Identifier property(exec, subscript->toString(exec));
4299 result = baseValue->get(exec, property);
4300 }
4301
4302 VM_CHECK_EXCEPTION_AT_END();
4303 return result;
4304}
4305
4306JSValue* Machine::cti_op_resolve_func(CTI_ARGS)
4307{
4308 ExecState* exec = ARG_exec;
4309 ScopeChainNode* scopeChain = ARG_scopeChain;
4310
4311 ScopeChainIterator iter = scopeChain->begin();
4312 ScopeChainIterator end = scopeChain->end();
4313
4314 // FIXME: add scopeDepthIsZero optimization
4315
4316 ASSERT(iter != end);
4317
4318 Identifier& ident = *ARG_id1;
4319 JSObject* base;
4320 do {
4321 base = *iter;
4322 PropertySlot slot(base);
4323 if (base->getPropertySlot(exec, ident, slot)) {
4324 // ECMA 11.2.3 says that if we hit an activation the this value should be null.
4325 // However, section 10.2.3 says that in the case where the value provided
4326 // by the caller is null, the global object should be used. It also says
4327 // that the section does not apply to internal functions, but for simplicity
4328 // of implementation we use the global object anyway here. This guarantees
4329 // that in host objects you always get a valid object for this.
4330 // We also handle wrapper substitution for the global object at the same time.
4331 JSObject* thisObj = base->toThisObject(exec);
4332 JSValue* result = slot.getValue(exec, ident);
4333 VM_CHECK_EXCEPTION_AT_END();
4334
4335 ARG_set2ndResult(result);
4336 return thisObj;
4337 }
4338 ++iter;
4339 } while (iter != end);
4340
4341 CodeBlock* codeBlock = ARG_codeBlock;
4342 ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
4343 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
4344 exec->setException(createUndefinedVariableError(exec, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock));
4345
4346 VM_CHECK_EXCEPTION_AT_END();
4347 return 0;
4348}
4349
4350JSValue* Machine::cti_op_sub(CTI_ARGS)
4351{
4352 JSValue* src1 = ARG_src1;
4353 JSValue* src2 = ARG_src2;
4354
4355 double left;
4356 double right;
4357 if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
4358 return jsNumber(ARG_exec, left - right);
4359 else {
4360 ExecState* exec = ARG_exec;
4361 JSValue* result = jsNumber(exec, src1->toNumber(exec) - src2->toNumber(exec));
4362 VM_CHECK_EXCEPTION_AT_END();
4363 return result;
4364 }
4365}
4366
4367void Machine::cti_op_put_by_val(CTI_ARGS)
4368{
4369 ExecState* exec = ARG_exec;
4370 Machine* machine = exec->machine();
4371
4372 JSValue* baseValue = ARG_src1;
4373 JSValue* subscript = ARG_src2;
4374 JSValue* value = ARG_src3;
4375
4376 unsigned i;
4377
4378 bool isUInt32 = JSImmediate::getUInt32(subscript, i);
4379 if (LIKELY(isUInt32)) {
4380 if (machine->isJSArray(baseValue)) {
4381 JSArray* jsArray = static_cast<JSArray*>(baseValue);
4382 if (jsArray->canSetIndex(i))
4383 jsArray->setIndex(i, value);
4384 else
4385 jsArray->JSArray::put(exec, i, value);
4386 } else
4387 baseValue->put(exec, i, value);
4388 } else {
4389 Identifier property(exec, subscript->toString(exec));
4390 if (!exec->hadException()) { // Don't put to an object if toString threw an exception.
4391 PutPropertySlot slot;
4392 baseValue->put(exec, property, value, slot);
4393 }
4394 }
4395
4396 VM_CHECK_EXCEPTION_AT_END();
4397}
4398
4399JSValue* Machine::cti_op_lesseq(CTI_ARGS)
4400{
4401 ExecState* exec = ARG_exec;
4402 JSValue* result = jsBoolean(jsLessEq(exec, ARG_src1, ARG_src2));
4403 VM_CHECK_EXCEPTION_AT_END();
4404 return result;
4405}
4406
4407int Machine::cti_op_loop_if_true(CTI_ARGS)
4408{
4409 JSValue* src1 = ARG_src1;
4410
4411 ExecState* exec = ARG_exec;
4412
4413 bool result = src1->toBoolean(exec);
4414 VM_CHECK_EXCEPTION_AT_END();
4415 return result;
4416}
4417
4418JSValue* Machine::cti_op_negate(CTI_ARGS)
4419{
4420 JSValue* src = ARG_src1;
4421
4422 ExecState* exec = ARG_exec;
4423
4424 double v;
4425 if (fastIsNumber(src, v))
4426 return jsNumber(exec, -v);
4427 else {
4428 JSValue* result = jsNumber(exec, -src->toNumber(exec));
4429 VM_CHECK_EXCEPTION_AT_END();
4430 return result;
4431 }
4432}
4433
4434JSValue* Machine::cti_op_resolve_base(CTI_ARGS)
4435{
4436 return inlineResolveBase(ARG_exec, *ARG_id1, ARG_scopeChain);
4437}
4438
4439JSValue* Machine::cti_op_resolve_skip(CTI_ARGS)
4440{
4441 ExecState* exec = ARG_exec;
4442 ScopeChainNode* scopeChain = ARG_scopeChain;
4443
4444 int skip = ARG_int2;
4445
4446 ScopeChainIterator iter = scopeChain->begin();
4447 ScopeChainIterator end = scopeChain->end();
4448 ASSERT(iter != end);
4449 while (skip--) {
4450 ++iter;
4451 ASSERT(iter != end);
4452 }
4453 Identifier& ident = *ARG_id1;
4454 do {
4455 JSObject* o = *iter;
4456 PropertySlot slot(o);
4457 if (o->getPropertySlot(exec, ident, slot)) {
4458 JSValue* result = slot.getValue(exec, ident);
4459 VM_CHECK_EXCEPTION_AT_END();
4460 return result;
4461 }
4462 } while (++iter != end);
4463
4464 CodeBlock* codeBlock = ARG_codeBlock;
4465 ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
4466 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
4467 exec->setException(createUndefinedVariableError(exec, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock));
4468
4469 VM_CHECK_EXCEPTION_AT_END();
4470 return 0;
4471}
4472
4473JSValue* Machine::cti_op_div(CTI_ARGS)
4474{
4475 ExecState* exec = ARG_exec;
4476 JSValue* src1 = ARG_src1;
4477 JSValue* src2 = ARG_src2;
4478
4479 double left;
4480 double right;
4481 if (fastIsNumber(src1, left) && fastIsNumber(src2, right))
4482 return jsNumber(exec, left / right);
4483 else {
4484 JSValue* result = jsNumber(exec, src1->toNumber(exec) / src2->toNumber(exec));
4485 VM_CHECK_EXCEPTION_AT_END();
4486 return result;
4487 }
4488}
4489
4490JSValue* Machine::cti_op_pre_dec(CTI_ARGS)
4491{
4492 JSValue* v = ARG_src1;
4493
4494 ExecState* exec = ARG_exec;
4495 JSValue* result = jsNumber(exec, v->toNumber(exec) - 1);
4496 VM_CHECK_EXCEPTION_AT_END();
4497 return result;
4498}
4499
4500int Machine::cti_op_jless(CTI_ARGS)
4501{
4502 JSValue* src1 = ARG_src1;
4503 JSValue* src2 = ARG_src2;
4504 ExecState* exec = ARG_exec;
4505
4506 bool result = jsLess(exec, src1, src2);
4507 VM_CHECK_EXCEPTION_AT_END();
4508 return result;
4509}
4510
4511JSValue* Machine::cti_op_not(CTI_ARGS)
4512{
4513 JSValue* src = ARG_src1;
4514
4515 ExecState* exec = ARG_exec;
4516
4517 JSValue* result = jsBoolean(!src->toBoolean(exec));
4518 VM_CHECK_EXCEPTION_AT_END();
4519 return result;
4520}
4521
4522int SFX_CALL Machine::cti_op_jtrue(CTI_ARGS)
4523{
4524 JSValue* src1 = ARG_src1;
4525
4526 ExecState* exec = ARG_exec;
4527
4528 bool result = src1->toBoolean(exec);
4529 VM_CHECK_EXCEPTION_AT_END();
4530 return result;
4531}
4532
4533JSValue* Machine::cti_op_post_inc(CTI_ARGS)
4534{
4535 JSValue* v = ARG_src1;
4536
4537 ExecState* exec = ARG_exec;
4538
4539 JSValue* number = v->toJSNumber(exec);
4540 VM_CHECK_EXCEPTION(JSValue*);
4541 ARG_set2ndResult(jsNumber(exec, number->uncheckedGetNumber() + 1));
4542 return number;
4543}
4544
4545JSValue* Machine::cti_op_eq(CTI_ARGS)
4546{
4547 JSValue* src1 = ARG_src1;
4548 JSValue* src2 = ARG_src2;
4549
4550 if (JSImmediate::areBothImmediateNumbers(src1, src2))
4551 return jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
4552 else {
4553 ExecState* exec = ARG_exec;
4554 JSValue* result = jsBoolean(equal(exec, src1, src2));
4555 VM_CHECK_EXCEPTION_AT_END();
4556 return result;
4557 }
4558}
4559
4560JSValue* Machine::cti_op_lshift(CTI_ARGS)
4561{
4562 JSValue* val = ARG_src1;
4563 JSValue* shift = ARG_src2;
4564
4565 ExecState* exec = ARG_exec;
4566
4567 int32_t left;
4568 uint32_t right;
4569 if (JSImmediate::areBothImmediateNumbers(val, shift))
4570 return jsNumber(exec, JSImmediate::getTruncatedInt32(val) << (JSImmediate::getTruncatedUInt32(shift) & 0x1f));
4571 else if (fastToInt32(val, left) && fastToUInt32(shift, right))
4572 return jsNumber(exec, left << (right & 0x1f));
4573 else {
4574 JSValue* result = jsNumber(exec, (val->toInt32(exec)) << (shift->toUInt32(exec) & 0x1f));
4575 VM_CHECK_EXCEPTION_AT_END();
4576 return result;
4577 }
4578}
4579
4580JSValue* Machine::cti_op_bitand(CTI_ARGS)
4581{
4582 JSValue* src1 = ARG_src1;
4583 JSValue* src2 = ARG_src2;
4584
4585 ExecState* exec = ARG_exec;
4586
4587 int32_t left;
4588 int32_t right;
4589 if (fastToInt32(src1, left) && fastToInt32(src2, right))
4590 return jsNumber(exec, left & right);
4591 else {
4592 JSValue* result = jsNumber(exec, src1->toInt32(exec) & src2->toInt32(exec));
4593 VM_CHECK_EXCEPTION_AT_END();
4594 return result;
4595 }
4596}
4597
4598JSValue* Machine::cti_op_rshift(CTI_ARGS)
4599{
4600 JSValue* val = ARG_src1;
4601 JSValue* shift = ARG_src2;
4602
4603 ExecState* exec = ARG_exec;
4604
4605 int32_t left;
4606 uint32_t right;
4607 if (JSImmediate::areBothImmediateNumbers(val, shift))
4608 return JSImmediate::rightShiftImmediateNumbers(val, shift);
4609 else if (fastToInt32(val, left) && fastToUInt32(shift, right))
4610 return jsNumber(exec, left >> (right & 0x1f));
4611 else {
4612 JSValue* result = jsNumber(exec, (val->toInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
4613 VM_CHECK_EXCEPTION_AT_END();
4614 return result;
4615 }
4616}
4617
4618JSValue* Machine::cti_op_bitnot(CTI_ARGS)
4619{
4620 JSValue* src = ARG_src1;
4621
4622 ExecState* exec = ARG_exec;
4623
4624 int value;
4625 if (fastToInt32(src, value))
4626 return jsNumber(exec, ~value);
4627
4628 JSValue* result = jsNumber(exec, ~src->toInt32(exec));
4629 VM_CHECK_EXCEPTION_AT_END();
4630 return result;
4631}
4632
4633JSValue* Machine::cti_op_resolve_with_base(CTI_ARGS)
4634{
4635 ExecState* exec = ARG_exec;
4636 ScopeChainNode* scopeChain = ARG_scopeChain;
4637
4638 ScopeChainIterator iter = scopeChain->begin();
4639 ScopeChainIterator end = scopeChain->end();
4640
4641 // FIXME: add scopeDepthIsZero optimization
4642
4643 ASSERT(iter != end);
4644
4645 Identifier& ident = *ARG_id1;
4646 JSObject* base;
4647 do {
4648 base = *iter;
4649 PropertySlot slot(base);
4650 if (base->getPropertySlot(exec, ident, slot)) {
4651 JSValue* result = slot.getValue(exec, ident);
4652 VM_CHECK_EXCEPTION_AT_END();
4653 ARG_set2ndResult(result);
4654 return base;
4655 }
4656 ++iter;
4657 } while (iter != end);
4658
4659 CodeBlock* codeBlock = ARG_codeBlock;
4660 ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
4661 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
4662 exec->setException(createUndefinedVariableError(exec, ident, codeBlock->instructions.begin() + vPCIndex, codeBlock));
4663
4664 VM_CHECK_EXCEPTION_AT_END();
4665 return 0;
4666}
4667
4668JSValue* Machine::cti_op_new_func_exp(CTI_ARGS)
4669{
4670 return ARG_funcexp1->makeFunction(ARG_exec, ARG_scopeChain);
4671}
4672
4673JSValue* Machine::cti_op_mod(CTI_ARGS)
4674{
4675 JSValue* dividendValue = ARG_src1;
4676 JSValue* divisorValue = ARG_src2;
4677
4678 ExecState* exec = ARG_exec;
4679 double d = dividendValue->toNumber(exec);
4680 JSValue* result = jsNumber(exec, fmod(d, divisorValue->toNumber(exec)));
4681 VM_CHECK_EXCEPTION_AT_END();
4682 return result;
4683}
4684
4685JSValue* Machine::cti_op_less(CTI_ARGS)
4686{
4687 ExecState* exec = ARG_exec;
4688 JSValue* result = jsBoolean(jsLess(exec, ARG_src1, ARG_src2));
4689 VM_CHECK_EXCEPTION_AT_END();
4690 return result;
4691}
4692
4693JSValue* Machine::cti_op_neq(CTI_ARGS)
4694{
4695 JSValue* src1 = ARG_src1;
4696 JSValue* src2 = ARG_src2;
4697
4698 if (JSImmediate::areBothImmediateNumbers(src1, src2))
4699 return jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
4700 else {
4701 ExecState* exec = ARG_exec;
4702 JSValue* result = jsBoolean(!equal(exec, src1, src2));
4703 VM_CHECK_EXCEPTION_AT_END();
4704 return result;
4705 }
4706}
4707
4708JSValue* Machine::cti_op_post_dec(CTI_ARGS)
4709{
4710 JSValue* v = ARG_src1;
4711
4712 ExecState* exec = ARG_exec;
4713
4714 JSValue* number = v->toJSNumber(exec);
4715 VM_CHECK_EXCEPTION(JSValue*);
4716
4717 ARG_set2ndResult(jsNumber(exec, number->uncheckedGetNumber() - 1));
4718 return number;
4719}
4720
4721JSValue* Machine::cti_op_urshift(CTI_ARGS)
4722{
4723 JSValue* val = ARG_src1;
4724 JSValue* shift = ARG_src2;
4725
4726 ExecState* exec = ARG_exec;
4727
4728 if (JSImmediate::areBothImmediateNumbers(val, shift) && !JSImmediate::isNegative(val))
4729 return JSImmediate::rightShiftImmediateNumbers(val, shift);
4730 else {
4731 JSValue* result = jsNumber(exec, (val->toUInt32(exec)) >> (shift->toUInt32(exec) & 0x1f));
4732 VM_CHECK_EXCEPTION_AT_END();
4733 return result;
4734 }
4735}
4736
4737JSValue* Machine::cti_op_bitxor(CTI_ARGS)
4738{
4739 JSValue* src1 = ARG_src1;
4740 JSValue* src2 = ARG_src2;
4741
4742 ExecState* exec = ARG_exec;
4743
4744 JSValue* result = jsNumber(exec, src1->toInt32(exec) ^ src2->toInt32(exec));
4745 VM_CHECK_EXCEPTION_AT_END();
4746 return result;
4747}
4748
4749JSValue* Machine::cti_op_new_regexp(CTI_ARGS)
4750{
4751 return new (ARG_exec) RegExpObject(ARG_scopeChain->globalObject()->regExpPrototype(), ARG_regexp1);
4752}
4753
4754JSValue* Machine::cti_op_bitor(CTI_ARGS)
4755{
4756 JSValue* src1 = ARG_src1;
4757 JSValue* src2 = ARG_src2;
4758
4759 ExecState* exec = ARG_exec;
4760
4761 JSValue* result = jsNumber(exec, src1->toInt32(exec) | src2->toInt32(exec));
4762 VM_CHECK_EXCEPTION_AT_END();
4763 return result;
4764}
4765
4766JSValue* Machine::cti_op_call_eval(CTI_ARGS)
4767{
4768 ExecState* exec = ARG_exec;
4769 RegisterFile* registerFile = ARG_registerFile;
4770 Register* r = ARG_r;
4771 CodeBlock* codeBlock = ARG_codeBlock;
4772 ScopeChainNode* scopeChain = ARG_scopeChain;
4773
4774 Machine* machine = exec->machine();
4775 JSValue* exceptionValue = 0;
4776
4777 JSValue* funcVal = ARG_src1;
4778 JSValue* baseVal = ARG_src2;
4779 int firstArg = ARG_int3;
4780 int argCount = ARG_int4;
4781
4782 if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
4783 JSObject* thisObject = static_cast<JSObject*>(r[codeBlock->thisRegister].jsValue(exec));
4784 JSValue* result = machine->callEval(exec, thisObject, scopeChain, registerFile, r, firstArg, argCount, exceptionValue);
4785 JSVALUE_VM_CHECK_EXCEPTION_ARG(exceptionValue);
4786 return result;
4787 }
4788
4789 return JSImmediate::impossibleValue();
4790}
4791
4792void* Machine::cti_op_throw(CTI_ARGS)
4793{
4794 ExecState* exec = ARG_exec;
4795 CodeBlock* codeBlock = ARG_codeBlock;
4796 ScopeChainNode* scopeChain = ARG_scopeChain;
4797 Register* r = ARG_r;
4798
4799 ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
4800 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
4801
4802 JSValue* exceptionValue = ARG_src1;
4803 Instruction* handlerVPC = ARG_exec->machine()->throwException(exec, exceptionValue, codeBlock->instructions.begin() + vPCIndex, codeBlock, scopeChain, r, true);
4804
4805 if (handlerVPC) {
4806 exec->setException(exceptionValue);
4807 ARG_setScopeChain(scopeChain);
4808 ARG_setCodeBlock(codeBlock);
4809 ARG_setR(r);
4810
4811 void* catchRoutine = codeBlock->nativeExceptionCodeForHandlerVPC(handlerVPC);
4812 ASSERT(catchRoutine);
4813 ctiSetReturnAddress(&CTI_RETURN_ADDRESS, catchRoutine);
4814 return catchRoutine;
4815 } else {
4816 exec->clearException();
4817 *ARG_exception = exceptionValue;
4818 return JSImmediate::nullImmediate();
4819 }
4820}
4821
4822JSPropertyNameIterator* Machine::cti_op_get_pnames(CTI_ARGS)
4823{
4824 return JSPropertyNameIterator::create(ARG_exec, ARG_src1);
4825}
4826
4827JSValue* Machine::cti_op_next_pname(CTI_ARGS)
4828{
4829 JSPropertyNameIterator* it = ARG_pni1;
4830 JSValue* temp = it->next(ARG_exec);
4831 if (!temp)
4832 it->invalidate();
4833 return temp;
4834}
4835
4836void Machine::cti_op_push_scope(CTI_ARGS)
4837{
4838 ExecState* exec = ARG_exec;
4839
4840 JSValue* v = ARG_src1;
4841 JSObject* o = v->toObject(exec);
4842 VM_CHECK_EXCEPTION_v();
4843
4844 ScopeChainNode* newScopeChain = ARG_scopeChain->push(o);
4845 ARG_setScopeChain(newScopeChain);
4846 exec->m_scopeChain = newScopeChain;
4847}
4848
4849void Machine::cti_op_pop_scope(CTI_ARGS)
4850{
4851 ExecState* exec = ARG_exec;
4852
4853 ScopeChainNode* newScopeChain = ARG_scopeChain->pop();
4854 ARG_setScopeChain(newScopeChain);
4855 exec->m_scopeChain = newScopeChain;
4856}
4857
4858JSValue* Machine::cti_op_typeof(CTI_ARGS)
4859{
4860 return jsTypeStringForValue(ARG_exec, ARG_src1);
4861}
4862
4863JSValue* Machine::cti_op_stricteq(CTI_ARGS)
4864{
4865 JSValue* src1 = ARG_src1;
4866 JSValue* src2 = ARG_src2;
4867
4868 if (JSImmediate::areBothImmediateNumbers(src1, src2))
4869 return jsBoolean(reinterpret_cast<intptr_t>(src1) == reinterpret_cast<intptr_t>(src2));
4870 else {
4871 ExecState* exec = ARG_exec;
4872 JSValue* result = jsBoolean(strictEqual(src1, src2));
4873 VM_CHECK_EXCEPTION_AT_END();
4874 return result;
4875 }
4876}
4877
4878JSValue* Machine::cti_op_nstricteq(CTI_ARGS)
4879{
4880 JSValue* src1 = ARG_src1;
4881 JSValue* src2 = ARG_src2;
4882
4883 if (JSImmediate::areBothImmediateNumbers(src1, src2))
4884 return jsBoolean(reinterpret_cast<intptr_t>(src1) != reinterpret_cast<intptr_t>(src2));
4885 else {
4886 ExecState* exec = ARG_exec;
4887 JSValue* result = jsBoolean(!strictEqual(src1, src2));
4888 VM_CHECK_EXCEPTION_AT_END();
4889 return result;
4890 }
4891}
4892
4893JSValue* Machine::cti_op_to_jsnumber(CTI_ARGS)
4894{
4895 JSValue* src = ARG_src1;
4896 ExecState* exec = ARG_exec;
4897
4898 JSValue* result = src->toJSNumber(exec);
4899 VM_CHECK_EXCEPTION_AT_END();
4900 return result;
4901}
4902
4903JSValue* Machine::cti_op_in(CTI_ARGS)
4904{
4905 ExecState* exec = ARG_exec;
4906 JSValue* baseVal = ARG_src2;
4907
4908 if (!baseVal->isObject()) {
4909 CodeBlock* codeBlock = ARG_codeBlock;
4910 ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(CTI_RETURN_ADDRESS));
4911 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
4912 exec->setException(createInvalidParamError(exec, "in", baseVal, codeBlock->instructions.begin() + vPCIndex, codeBlock));
4913 VM_CHECK_EXCEPTION(JSValue*);
4914 }
4915
4916 JSValue* propName = ARG_src1;
4917 JSObject* baseObj = static_cast<JSObject*>(baseVal);
4918
4919 uint32_t i;
4920 if (propName->getUInt32(i))
4921 return jsBoolean(baseObj->hasProperty(exec, i));
4922
4923 Identifier property(exec, propName->toString(exec));
4924 VM_CHECK_EXCEPTION(JSValue*);
4925 return jsBoolean(baseObj->hasProperty(exec, property));
4926}
4927
4928JSValue* Machine::cti_op_push_new_scope(CTI_ARGS)
4929{
4930 ExecState* exec = ARG_exec;
4931 JSObject* scope = new (exec) JSStaticScopeObject(exec, *ARG_id1, ARG_src2, DontDelete);
4932
4933 ScopeChainNode* newScopeChain = ARG_scopeChain->push(scope);
4934 ARG_setScopeChain(newScopeChain);
4935 exec->m_scopeChain = newScopeChain;
4936
4937 return scope;
4938}
4939
4940void Machine::cti_op_jmp_scopes(CTI_ARGS)
4941{
4942 ExecState* exec = ARG_exec;
4943 unsigned count = ARG_int1;
4944
4945 ScopeChainNode* tmp = ARG_scopeChain;
4946 while (count--)
4947 tmp = tmp->pop();
4948
4949 ARG_setScopeChain(tmp);
4950 exec->m_scopeChain = tmp;
4951}
4952
4953void Machine::cti_op_put_by_index(CTI_ARGS)
4954{
4955 ExecState* exec = ARG_exec;
4956 unsigned property = ARG_int2;
4957
4958 ARG_src1->put(exec, property, ARG_src3);
4959}
4960
4961void* Machine::cti_op_switch_imm(CTI_ARGS)
4962{
4963 JSValue* scrutinee = ARG_src1;
4964 unsigned tableIndex = ARG_int2;
4965
4966 CodeBlock* codeBlock = ARG_codeBlock;
4967
4968 if (JSImmediate::isNumber(scrutinee)) {
4969 int32_t value = JSImmediate::getTruncatedInt32(scrutinee);
4970 return codeBlock->immediateSwitchJumpTables[tableIndex].ctiForValue(value);
4971 }
4972
4973 return codeBlock->immediateSwitchJumpTables[tableIndex].ctiDefault;
4974}
4975
4976void* Machine::cti_op_switch_char(CTI_ARGS)
4977{
4978 JSValue* scrutinee = ARG_src1;
4979 unsigned tableIndex = ARG_int2;
4980
4981 CodeBlock* codeBlock = ARG_codeBlock;
4982
4983 void* result = codeBlock->characterSwitchJumpTables[tableIndex].ctiDefault;
4984
4985 if (scrutinee->isString()) {
4986 UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
4987 if (value->size() == 1)
4988 result = codeBlock->characterSwitchJumpTables[tableIndex].ctiForValue(value->data()[0]);
4989 }
4990
4991 return result;
4992}
4993
4994void* Machine::cti_op_switch_string(CTI_ARGS)
4995{
4996 JSValue* scrutinee = ARG_src1;
4997 unsigned tableIndex = ARG_int2;
4998
4999 CodeBlock* codeBlock = ARG_codeBlock;
5000
5001 void* result = codeBlock->stringSwitchJumpTables[tableIndex].ctiDefault;
5002
5003 if (scrutinee->isString()) {
5004 UString::Rep* value = static_cast<JSString*>(scrutinee)->value().rep();
5005 result = codeBlock->stringSwitchJumpTables[tableIndex].ctiForValue(value);
5006 }
5007
5008 return result;
5009}
5010
5011JSValue* Machine::cti_op_del_by_val(CTI_ARGS)
5012{
5013 ExecState* exec = ARG_exec;
5014
5015 JSValue* baseValue = ARG_src1;
5016 JSObject* baseObj = baseValue->toObject(exec); // may throw
5017
5018 JSValue* subscript = ARG_src2;
5019 JSValue* result;
5020 uint32_t i;
5021 if (subscript->getUInt32(i))
5022 result = jsBoolean(baseObj->deleteProperty(exec, i));
5023 else {
5024 VM_CHECK_EXCEPTION(JSValue*);
5025 Identifier property(exec, subscript->toString(exec));
5026 VM_CHECK_EXCEPTION(JSValue*);
5027 result = jsBoolean(baseObj->deleteProperty(exec, property));
5028 }
5029
5030 VM_CHECK_EXCEPTION_AT_END();
5031 return result;
5032}
5033
5034void Machine::cti_op_put_getter(CTI_ARGS)
5035{
5036 ExecState* exec = ARG_exec;
5037
5038 ASSERT(ARG_src1->isObject());
5039 JSObject* baseObj = static_cast<JSObject*>(ARG_src1);
5040 Identifier& ident = *ARG_id2;
5041 ASSERT(ARG_src3->isObject());
5042 baseObj->defineGetter(exec, ident, static_cast<JSObject*>(ARG_src3));
5043}
5044
5045void Machine::cti_op_put_setter(CTI_ARGS)
5046{
5047 ExecState* exec = ARG_exec;
5048
5049 ASSERT(ARG_src1->isObject());
5050 JSObject* baseObj = static_cast<JSObject*>(ARG_src1);
5051 Identifier& ident = *ARG_id2;
5052 ASSERT(ARG_src3->isObject());
5053 baseObj->defineSetter(exec, ident, static_cast<JSObject*>(ARG_src3));
5054}
5055
5056JSValue* Machine::cti_op_new_error(CTI_ARGS)
5057{
5058 ExecState* exec = ARG_exec;
5059 CodeBlock* codeBlock = ARG_codeBlock;
5060 unsigned type = ARG_int1;
5061 JSValue* message = ARG_src2;
5062 unsigned lineNumber = ARG_int3;
5063
5064 return Error::create(exec, static_cast<ErrorType>(type), message->toString(exec), lineNumber, codeBlock->ownerNode->sourceId(), codeBlock->ownerNode->sourceURL());
5065}
5066
5067void Machine::cti_op_debug(CTI_ARGS)
5068{
5069 ExecState* exec = ARG_exec;
5070 CodeBlock* codeBlock = ARG_codeBlock;
5071 ScopeChainNode* scopeChain = ARG_scopeChain;
5072 Register* r = ARG_r;
5073
5074 int debugHookID = ARG_int1;
5075 int firstLine = ARG_int2;
5076 int lastLine = ARG_int3;
5077
5078 exec->machine()->debug(exec, codeBlock, scopeChain, r, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
5079}
5080
5081JSValue* Machine::cti_op_eq_null(CTI_ARGS)
5082{
5083 JSValue* src = ARG_src1;
5084 if (src->isUndefinedOrNull())
5085 return jsBoolean(true);
5086
5087 return jsBoolean(!JSImmediate::isImmediate(src) && static_cast<JSCell*>(src)->masqueradeAsUndefined());
5088}
5089
5090JSValue* Machine::cti_op_neq_null(CTI_ARGS)
5091{
5092 JSValue* src = ARG_src1;
5093 if (src->isUndefinedOrNull())
5094 return jsBoolean(false);
5095
5096 return jsBoolean(JSImmediate::isImmediate(src) || !static_cast<JSCell*>(src)->masqueradeAsUndefined());
5097}
5098
5099void* Machine::cti_vm_throw(CTI_ARGS)
5100{
5101 ExecState* exec = ARG_exec;
5102 CodeBlock* codeBlock = ARG_codeBlock;
5103 ScopeChainNode* scopeChain = ARG_scopeChain;
5104 Register* r = ARG_r;
5105
5106 ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(exec->ctiReturnAddress()));
5107 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(exec->ctiReturnAddress());
5108
5109 ASSERT(exec->hadException());
5110
5111 JSValue* exceptionValue = exec->exception();
5112
5113 Instruction* handlerVPC = ARG_exec->machine()->throwException(exec, exceptionValue, codeBlock->instructions.begin() + vPCIndex, codeBlock, scopeChain, r, false);
5114
5115 if (handlerVPC) {
5116 exec->setException(exceptionValue);
5117 ARG_setScopeChain(scopeChain);
5118 ARG_setCodeBlock(codeBlock);
5119 ARG_setR(r);
5120
5121 void* catchRoutine = codeBlock->nativeExceptionCodeForHandlerVPC(handlerVPC);
5122 ASSERT(catchRoutine);
5123 ctiSetReturnAddress(&CTI_RETURN_ADDRESS, catchRoutine);
5124 return catchRoutine;
5125 } else {
5126 exec->clearException();
5127 *ARG_exception = exceptionValue;
5128 return JSImmediate::nullImmediate();
5129 }
5130}
5131
5132#undef VM_CHECK_EXCEPTION
5133#undef VM_CHECK_EXCEPTION_v
5134#undef VM_CHECK_EXCEPTION_AT_END
5135
5136#endif // ENABLE(CTI)
5137
5138} // namespace JSC
Note: See TracBrowser for help on using the repository browser.