https://bugs.webkit.org/show_bug.cgi?id=74331
Reviewed by Geoffrey Garen.
.:
* Source/autotools/symbols.filter: Removed symbol no longer present.
Source/JavaScriptCore:
This is a megapatch which frees us from the chains of virtual destructors.
In order to remove the virtual destructors, which are the last of the virtual
functions, from the JSCell hierarchy, we need to add the ClassInfo pointer to
the cell rather than to the structure because in order to be able to lazily call
the static destroy() functions that will replace the virtual destructors, we
need to be able to access the ClassInfo without the danger of the object's
Structure being collected before the object itself.
After adding the ClassInfo to the cell, we can then begin to remove our use
of vptrs for optimizations within the JIT and the GC. When we have removed
all of the stored vptrs from JSGlobalData, we can then also remove all of
the related VPtrStealingHack code.
The replacement for virtual destructors will be to add a static destroy function
pointer to the MethodTable stored in ClassInfo. Any subclass of JSCell that has
a non-trivial destructor will require its own static destroy function to static
call its corresponding destructor, which will now be non-virtual. In future
patches we will slowly move away from destructors altogether as we make more and
more objects backed by GC memory rather than malloc-ed memory. The GC will now
call the static destroy method rather than the virtual destructor.
As we go through the hierarchy and add static destroy functions to classes,
we will also add a new assert, ASSERT_HAS_TRIVIAL_DESTRUCTOR, to those classes
to which it applies. The future goal is to eventually have every class have that assert.
* API/JSCallbackConstructor.cpp:
(JSC::JSCallbackConstructor::destroy): Add a destroy function to statically call
~JSCallbackConstructor because it has some extra destruction logic.
* API/JSCallbackConstructor.h:
* API/JSCallbackFunction.cpp: Add trivial destructor assert for JSCallbackFunction.
* API/JSCallbackObject.cpp: Add a destroy function to statically call ~JSCallbackObject
because it has a member OwnPtr that needs destruction.
(JSC::::destroy):
* API/JSCallbackObject.h:
* JavaScriptCore.exp: Add/remove necessary symbols for JSC.
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Same for Windows symbols.
* debugger/DebuggerActivation.cpp: DebuggerActivation, for some strange reason, didn't
have its own ClassInfo despite the fact that it overrides a number of MethodTable
methods. Added the ClassInfo, along with an assertion that its destructor is trivial.
* debugger/DebuggerActivation.h:
* dfg/DFGOperations.cpp: Remove global data first argument to isJSArray, isJSByteArray,
isJSString, as it is no longer necessary.
(JSC::DFG::putByVal):
* dfg/DFGRepatch.cpp: Ditto. Also remove uses of jsArrayVPtr in favor of using the
JSArray ClassInfo pointer.
(JSC::DFG::tryCacheGetByID):
* dfg/DFGSpeculativeJIT.cpp: Replace uses of the old vptrs with new ClassInfo
comparisons since we don't have vptrs anymore.
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality):
(JSC::DFG::SpeculativeJIT::compilePeepHoleBranch):
(JSC::DFG::SpeculativeJIT::checkArgumentTypes):
(JSC::DFG::SpeculativeJIT::compilePutByValForByteArray):
(JSC::DFG::SpeculativeJIT::compileGetTypedArrayLength):
(JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
(JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):
(JSC::DFG::SpeculativeJIT::compare):
(JSC::DFG::SpeculativeJIT::compileStrictEq):
(JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
* dfg/DFGSpeculativeJIT.h: Ditto.
(JSC::DFG::SpeculativeJIT::emitAllocateJSFinalObject):
* dfg/DFGSpeculativeJIT32_64.cpp: Ditto.
(JSC::DFG::SpeculativeJIT::compileObjectEquality):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
(JSC::DFG::SpeculativeJIT::compileLogicalNot):
(JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
(JSC::DFG::SpeculativeJIT::emitBranch):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp: Ditto.
(JSC::DFG::SpeculativeJIT::compileObjectEquality):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
(JSC::DFG::SpeculativeJIT::compileLogicalNot):
(JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
(JSC::DFG::SpeculativeJIT::emitBranch):
(JSC::DFG::SpeculativeJIT::compile):
* heap/Heap.cpp: Remove all uses of vptrs in GC optimizations and replace them with
ClassInfo comparisons.
(JSC::Heap::Heap):
* heap/MarkStack.cpp: Ditto.
(JSC::MarkStackThreadSharedData::markingThreadMain):
(JSC::visitChildren):
(JSC::SlotVisitor::drain):
* heap/MarkStack.h: Ditto.
(JSC::MarkStack::MarkStack):
* heap/MarkedBlock.cpp: Ditto.
(JSC::MarkedBlock::callDestructor):
(JSC::MarkedBlock::specializedSweep):
* heap/MarkedBlock.h: Ditto.
* heap/SlotVisitor.h: Ditto.
(JSC::SlotVisitor::SlotVisitor):
* heap/VTableSpectrum.cpp: Now that we don't have vptrs, we can't count them.
We'll have to rename this class and make it use ClassInfo ptrs in a future patch.
(JSC::VTableSpectrum::count):
* interpreter/Interpreter.cpp: Remove all global data arguments from isJSArray,
etc. functions.
(JSC::loadVarargs):
(JSC::Interpreter::tryCacheGetByID):
(JSC::Interpreter::privateExecute):
* jit/JIT.h: Remove vptr argument from emitAllocateBasicJSObject
* jit/JITInlineMethods.h: Remove vptr planting, and add ClassInfo planting,
remove all vtable related code.
(JSC::JIT::emitLoadCharacterString):
(JSC::JIT::emitAllocateBasicJSObject):
(JSC::JIT::emitAllocateJSFinalObject):
(JSC::JIT::emitAllocateJSFunction):
* jit/JITOpcodes.cpp: Replace vptr related branch code with corresponding ClassInfo.
(JSC::JIT::privateCompileCTIMachineTrampolines):
(JSC::JIT::emit_op_to_primitive):
(JSC::JIT::emit_op_convert_this):
* jit/JITOpcodes32_64.cpp: Ditto.
(JSC::JIT::privateCompileCTIMachineTrampolines):
(JSC::JIT::emit_op_to_primitive):
(JSC::JIT::emitSlow_op_eq):
(JSC::JIT::emitSlow_op_neq):
(JSC::JIT::compileOpStrictEq):
(JSC::JIT::emit_op_convert_this):
* jit/JITPropertyAccess.cpp: Ditto.
(JSC::JIT::stringGetByValStubGenerator):
(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::privateCompilePutByIdTransition):
(JSC::JIT::privateCompilePatchGetArrayLength):
* jit/JITPropertyAccess32_64.cpp: Ditto.
(JSC::JIT::stringGetByValStubGenerator):
(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::privateCompilePatchGetArrayLength):
* jit/JITStubs.cpp: Remove global data argument from isJSString, etc.
(JSC::JITThunks::tryCacheGetByID):
(JSC::DEFINE_STUB_FUNCTION):
* jit/SpecializedThunkJIT.h: Replace vptr related stuff with ClassInfo stuff.
(JSC::SpecializedThunkJIT::loadJSStringArgument):
* runtime/ArrayConstructor.cpp: Add trivial destructor assert.
* runtime/ArrayPrototype.cpp: Remove global data argument from isJSArray.
(JSC::arrayProtoFuncToString):
(JSC::arrayProtoFuncJoin):
(JSC::arrayProtoFuncPop):
(JSC::arrayProtoFuncPush):
(JSC::arrayProtoFuncShift):
(JSC::arrayProtoFuncSplice):
(JSC::arrayProtoFuncUnShift):
(JSC::arrayProtoFuncFilter):
(JSC::arrayProtoFuncMap):
(JSC::arrayProtoFuncEvery):
(JSC::arrayProtoFuncForEach):
(JSC::arrayProtoFuncSome):
(JSC::arrayProtoFuncReduce):
(JSC::arrayProtoFuncReduceRight):
* runtime/BooleanConstructor.cpp: Add trivial destructor assert.
* runtime/BooleanObject.cpp: Ditto.
* runtime/BooleanPrototype.cpp: Ditto.
* runtime/ClassInfo.h: Add destroy function pointer to MethodTable.
* runtime/DateConstructor.cpp: Add trivial destructor assert.
* runtime/DateInstance.cpp: Add destroy function for DateInstance because it has a RefPtr
that needs destruction.
(JSC::DateInstance::destroy):
* runtime/DateInstance.h:
* runtime/Error.cpp: Ditto (because of UString member).
(JSC::StrictModeTypeErrorFunction::destroy):
* runtime/Error.h:
* runtime/ErrorConstructor.cpp: Add trivial destructor assert.
* runtime/ErrorInstance.cpp: Ditto.
* runtime/ExceptionHelpers.cpp: Ditto.
* runtime/Executable.cpp: Add destroy functions for ExecutableBase and subclasses.
(JSC::ExecutableBase::destroy):
(JSC::NativeExecutable::destroy):
(JSC::ScriptExecutable::destroy):
(JSC::EvalExecutable::destroy):
(JSC::ProgramExecutable::destroy):
(JSC::FunctionExecutable::destroy):
* runtime/Executable.h:
* runtime/FunctionConstructor.cpp: Add trivial destructor assert.
* runtime/FunctionPrototype.cpp: Ditto. Also remove global data first arg from isJSArray.
(JSC::functionProtoFuncApply):
* runtime/GetterSetter.cpp: Ditto.
* runtime/InitializeThreading.cpp: Remove call to JSGlobalData::storeVPtrs since it no
longer exists.
(JSC::initializeThreadingOnce):
* runtime/InternalFunction.cpp: Remove vtableAnchor function, add trivial destructor assert,
remove first arg from isJSString.
(JSC::InternalFunction::displayName):
* runtime/InternalFunction.h: Remove VPtrStealingHack.
* runtime/JSAPIValueWrapper.cpp: Add trivial destructor assert.
* runtime/JSArray.cpp: Add static destroy to call ~JSArray. Replace vptr checks in
destructor with ClassInfo checks.
(JSC::JSArray::~JSArray):
(JSC::JSArray::destroy):
* runtime/JSArray.h: Remove VPtrStealingHack. Remove globalData argument from isJSArray
and change them to check the ClassInfo rather than the vptrs.
(JSC::isJSArray):
* runtime/JSBoundFunction.cpp: Add trival destructor assert. Remove first arg from isJSArray.
(JSC::boundFunctionCall):
(JSC::boundFunctionConstruct):
* runtime/JSByteArray.cpp: Add static destroy function, replace vptr checks with ClassInfo checks.
(JSC::JSByteArray::~JSByteArray):
(JSC::JSByteArray::destroy):
* runtime/JSByteArray.h: Remove VPtrStealingHack code.
(JSC::isJSByteArray):
* runtime/JSCell.cpp: Add trivial destructor assert. Add static destroy function.
(JSC::JSCell::destroy):
* runtime/JSCell.h: Remove VPtrStealingHack code. Add function for returning the offset
of the ClassInfo pointer in the object for use by the JIT. Add the ClassInfo pointer to
the JSCell itself, and grab it from the Structure. Remove the vptr and setVPtr functions,
as they are no longer used. Add a validatedClassInfo function to JSCell for any clients
that want to verify, while in Debug mode, that the ClassInfo contained in the cell is the
same one as that contained in the Structure. This isn't used too often, because most of
the places where we compare the ClassInfo to things can be called during destruction.
Since the Structure is unreliable during the phase when destructors are being called,
we can't call validatedClassInfo.
(JSC::JSCell::classInfoOffset):
(JSC::JSCell::structure):
(JSC::JSCell::classInfo):
* runtime/JSFunction.cpp: Remove VPtrStealingHack code. Add static destroy, remove vtableAnchor,
remove first arg from call to isJSString.
(JSC::JSFunction::destroy):
(JSC::JSFunction::displayName):
* runtime/JSFunction.h:
* runtime/JSGlobalData.cpp: Remove all VPtr stealing code and storage, including storeVPtrs,
as these vptrs are no longer needed in the codebase.
* runtime/JSGlobalData.h:
(JSC::TypedArrayDescriptor::TypedArrayDescriptor): Changed the TypedArrayDescriptor to use
ClassInfo rather than the vptr.
* runtime/JSGlobalObject.cpp: Add static destroy function.
(JSC::JSGlobalObject::destroy):
* runtime/JSGlobalObject.h:
* runtime/JSGlobalThis.cpp: Add trivial destructor assert.
* runtime/JSNotAnObject.cpp: Ditto.
* runtime/JSONObject.cpp: Ditto. Remove first arg from isJSArray calls.
(JSC::Stringifier::Holder::appendNextProperty):
(JSC::Walker::walk):
* runtime/JSObject.cpp:
(JSC::JSFinalObject::destroy):
(JSC::JSNonFinalObject::destroy):
(JSC::JSObject::destroy):
* runtime/JSObject.h: Add trivial destructor assert for JSObject, remove vtableAnchor
from JSNonFinalObject and JSFinalObject, add static destroy for JSFinalObject and
JSNonFinalObject, add isJSFinalObject utility function similar to isJSArray, remove all VPtrStealingHack code.
(JSC::JSObject::finishCreation):
(JSC::JSNonFinalObject::finishCreation):
(JSC::JSFinalObject::finishCreation):
(JSC::isJSFinalObject):
* runtime/JSPropertyNameIterator.cpp: Add static destroy.
(JSC::JSPropertyNameIterator::destroy):
* runtime/JSPropertyNameIterator.h:
* runtime/JSStaticScopeObject.cpp: Ditto.
(JSC::JSStaticScopeObject::destroy):
* runtime/JSStaticScopeObject.h: Ditto.
* runtime/JSString.cpp:
(JSC::JSString::destroy):
* runtime/JSString.h: Ditto. Remove VPtrStealingHack code. Also remove fixupVPtr code,
since we no longer need to fixup vptrs.
(JSC::jsSingleCharacterString):
(JSC::jsSingleCharacterSubstring):
(JSC::jsNontrivialString):
(JSC::jsString):
(JSC::jsSubstring8):
(JSC::jsSubstring):
(JSC::jsOwnedString):
(JSC::jsStringBuilder):
(JSC::isJSString):
* runtime/JSVariableObject.cpp:
(JSC::JSVariableObject::destroy):
* runtime/JSVariableObject.h: Ditto.
* runtime/JSWrapperObject.cpp:
* runtime/JSWrapperObject.h: Add trivial destructor assert.
* runtime/MathObject.cpp: Ditto.
* runtime/NativeErrorConstructor.cpp: Ditto.
* runtime/NumberConstructor.cpp: Ditto.
* runtime/NumberObject.cpp: Ditto.
* runtime/NumberPrototype.cpp: Ditto.
* runtime/ObjectConstructor.cpp: Ditto.
* runtime/ObjectPrototype.cpp: Ditto.
* runtime/Operations.h: Remove calls to fixupVPtr, remove first arg to isJSString.
(JSC::jsString):
(JSC::jsLess):
(JSC::jsLessEq):
* runtime/RegExp.cpp: Add static destroy.
(JSC::RegExp::destroy):
* runtime/RegExp.h:
* runtime/RegExpConstructor.cpp: Add static destroy for RegExpConstructor and RegExpMatchesArray.
(JSC::RegExpConstructor::destroy):
(JSC::RegExpMatchesArray::destroy):
* runtime/RegExpConstructor.h:
* runtime/RegExpMatchesArray.h:
* runtime/RegExpObject.cpp: Add static destroy.
(JSC::RegExpObject::destroy):
* runtime/RegExpObject.h:
* runtime/ScopeChain.cpp: Add trivial destructor assert.
* runtime/ScopeChain.h:
* runtime/StrictEvalActivation.cpp: Ditto.
* runtime/StringConstructor.cpp:
* runtime/StringObject.cpp: Ditto. Remove vtableAnchor.
* runtime/StringObject.h:
* runtime/StringPrototype.cpp: Ditto.
* runtime/Structure.cpp: Add static destroy.
(JSC::Structure::destroy):
* runtime/Structure.h: Move JSCell::finishCreation and JSCell constructor into Structure.h
because they need to have the full Structure type to access the ClassInfo to store in the JSCell.
(JSC::JSCell::setStructure):
(JSC::JSCell::validatedClassInfo):
(JSC::JSCell::JSCell):
(JSC::JSCell::finishCreation):
* runtime/StructureChain.cpp: Add static destroy.
(JSC::StructureChain::destroy):
* runtime/StructureChain.h:
* wtf/Assertions.h: Add new assertion ASSERT_HAS_TRIVIAL_DESTRUCTOR, which uses clangs
ability to tell us when a class has a trivial destructor. We will use this assert
more in future patches as we move toward having all JSC objects backed by GC memory,
which means moving away from using destructors/finalizers.
Source/JavaScriptGlue:
* UserObjectImp.cpp: Add static destroy function.
(UserObjectImp::destroy):
* UserObjectImp.h:
Source/WebCore:
No new tests.
Doing everything here that was done to the JSCell hierarchy in JavaScriptCore.
See the ChangeLog for this commit for a more in-depth description.
* WebCore.exp.in: Add/remove symbols.
* bindings/js/JSCanvasRenderingContext2DCustom.cpp: Remove first arg from isJSArray call.
(WebCore::JSCanvasRenderingContext2D::setWebkitLineDash):
* bindings/js/JSDOMBinding.cpp: Add trival destructor assert for DOMConstructorObject
and DOMConstructorWithDocument.
* bindings/js/JSDOMGlobalObject.cpp: Add static destroy. Add implementation for
scriptExecutionContext that dispatches to different functions in subclasses
depending on our current ClassInfo. We do this so that we can get rid of the
virtual-ness of scriptExecutionContext, because any virtual functions will throw
off the layout of the object and we'll crash at runtime.
(WebCore::JSDOMGlobalObject::destroy):
(WebCore::JSDOMGlobalObject::scriptExecutionContext):
* bindings/js/JSDOMGlobalObject.h:
* bindings/js/JSDOMWindowBase.cpp: Add static destroy.
(WebCore::JSDOMWindowBase::destroy):
* bindings/js/JSDOMWindowBase.h: De-virtualize scriptExecutionContext.
* bindings/js/JSDOMWindowShell.cpp: Add static destroy.
(WebCore::JSDOMWindowShell::destroy):
* bindings/js/JSDOMWindowShell.h:
* bindings/js/JSDOMWrapper.cpp: Add trivial destructor assert.
* bindings/js/JSDOMWrapper.h: Add a ClassInfo to JSDOMWrapper since it now overrides
a MethodTable function. Remove vtableAnchor virtual function.
* bindings/js/JSImageConstructor.cpp: Add trivial destructor assert.
* bindings/js/JSNodeCustom.cpp: Change implementation of pushEventHandlerScope so that
it dispatches to the correct function depending on the
identity of the class as specified by the ClassInfo.
See JSDOMGlobalObject::scriptExecutionContext for explanation.
(WebCore::JSNode::pushEventHandlerScope):
* bindings/js/JSWebSocketCustom.cpp: Remove first arg to isJSArray call.
(WebCore::JSWebSocketConstructor::constructJSWebSocket):
* bindings/js/JSWorkerContextBase.cpp: Add static destroy.
(WebCore::JSWorkerContextBase::destroy):
* bindings/js/JSWorkerContextBase.h:
* bindings/js/ScriptValue.cpp: Remove first arg to isJSArray call.
(WebCore::jsToInspectorValue):
* bindings/js/SerializedScriptValue.cpp: Ditto.
(WebCore::CloneSerializer::isArray):
(WebCore::CloneSerializer::getSparseIndex):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateHeader): Remove virtual-ness of any custom pushEventHandlerScope (see
JSNodeCustom::pushEventHandlerScope for explanation). Remove virtual toBoolean
for anybody who masquerades as undefined, since our JSObject implementation handles
this based on the TypeInfo in the Structure. Add trivial destructor assert for any
class other than DOMWindow or WorkerContexts.
(GenerateImplementation): Change ClassInfo definitions to use Base::s_info, since
typing the parent class more than once is duplication of information and increases
the likelihood of mistakes. Pass ClassInfo to TypeArrayDescriptors instead of vptr.
(GenerateConstructorDefinition): Add trivial destructor assert for all generated constructors.
* bridge/c/CRuntimeObject.cpp: Remove empty virtual destructor.
* bridge/c/CRuntimeObject.h:
* bridge/jni/jsc/JavaRuntimeObject.cpp: Ditto.
* bridge/jni/jsc/JavaRuntimeObject.h:
* bridge/objc/ObjCRuntimeObject.h: Ditto.
* bridge/objc/ObjCRuntimeObject.mm:
* bridge/objc/objc_runtime.h: Add static destroy for ObjcFallbackObjectImp. De-virtualize
toBoolean in the short term. Need longer term fix.
* bridge/objc/objc_runtime.mm:
(JSC::Bindings::ObjcFallbackObjectImp::destroy):
* bridge/qt/qt_runtime.cpp: Add static destroy to QtRuntimeMethod.
(JSC::Bindings::QtRuntimeMethod::destroy):
* bridge/qt/qt_runtime.h: De-virtualize ~QtRuntimeMethod.
* bridge/runtime_array.cpp: De-virtualize destructor. Add static destroy.
(JSC::RuntimeArray::destroy):
* bridge/runtime_array.h:
* bridge/runtime_method.cpp: Remove vtableAnchor. Add static destroy.
(JSC::RuntimeMethod::destroy):
* bridge/runtime_method.h:
* bridge/runtime_object.cpp: Add static destroy.
(JSC::Bindings::RuntimeObject::destroy):
* bridge/runtime_object.h:
Source/WebKit/mac:
* Plugins/Hosted/ProxyRuntimeObject.h: Remove empty virtual destructor.
* Plugins/Hosted/ProxyRuntimeObject.mm:
Source/WebKit2:
* WebProcess/Plugins/Netscape/JSNPMethod.cpp: Add trivial destructor assert.
* WebProcess/Plugins/Netscape/JSNPObject.cpp: Add static destroy.
(WebKit::JSNPObject::destroy):
* WebProcess/Plugins/Netscape/JSNPObject.h:
* win/WebKit2.def: Add/remove necessary symbols.
* win/WebKit2CFLite.def: Ditto.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@103083
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2011-12-16 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ De-virtualize destructors
+ https://bugs.webkit.org/show_bug.cgi?id=74331
+
+ Reviewed by Geoffrey Garen.
+
+ * Source/autotools/symbols.filter: Removed symbol no longer present.
+
2011-12-16 Carlos Garcia Campos <cgarcia@igalia.com>
[GTK] Update NEWS and configure.ac for 1.7.3 release
JSClassRelease(m_class);
}
+void JSCallbackConstructor::destroy(JSCell* cell)
+{
+ jsCast<JSCallbackConstructor*>(cell)->JSCallbackConstructor::~JSCallbackConstructor();
+}
+
static EncodedJSValue JSC_HOST_CALL constructJSCallback(ExecState* exec)
{
JSObject* constructor = exec->callee();
return constructor;
}
- virtual ~JSCallbackConstructor();
+ ~JSCallbackConstructor();
+ static void destroy(JSCell*);
JSClassRef classRef() const { return m_class; }
JSObjectCallAsConstructorCallback callback() const { return m_callback; }
static const ClassInfo s_info;
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSCallbackFunction);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSCallbackFunction);
const ClassInfo JSCallbackFunction::s_info = { "CallbackFunction", &InternalFunction::s_info, 0, 0, CREATE_METHOD_TABLE(JSCallbackFunction) };
return Structure::create(globalData, globalObject, proto, TypeInfo(GlobalObjectType, StructureFlags), &s_info);
}
+template <class Parent>
+void JSCallbackObject<Parent>::destroy(JSCell* cell)
+{
+ jsCast<JSCallbackObject*>(cell)->JSCallbackObject::~JSCallbackObject();
+}
+
void JSCallbackObjectData::finalize(Handle<Unknown> handle, void* context)
{
JSClassRef jsClass = static_cast<JSClassRef>(context);
private:
static UString className(const JSObject*);
+ static void destroy(JSCell*);
+
static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
+2011-12-16 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ De-virtualize destructors
+ https://bugs.webkit.org/show_bug.cgi?id=74331
+
+ Reviewed by Geoffrey Garen.
+
+ This is a megapatch which frees us from the chains of virtual destructors.
+
+ In order to remove the virtual destructors, which are the last of the virtual
+ functions, from the JSCell hierarchy, we need to add the ClassInfo pointer to
+ the cell rather than to the structure because in order to be able to lazily call
+ the static destroy() functions that will replace the virtual destructors, we
+ need to be able to access the ClassInfo without the danger of the object's
+ Structure being collected before the object itself.
+
+ After adding the ClassInfo to the cell, we can then begin to remove our use
+ of vptrs for optimizations within the JIT and the GC. When we have removed
+ all of the stored vptrs from JSGlobalData, we can then also remove all of
+ the related VPtrStealingHack code.
+
+ The replacement for virtual destructors will be to add a static destroy function
+ pointer to the MethodTable stored in ClassInfo. Any subclass of JSCell that has
+ a non-trivial destructor will require its own static destroy function to static
+ call its corresponding destructor, which will now be non-virtual. In future
+ patches we will slowly move away from destructors altogether as we make more and
+ more objects backed by GC memory rather than malloc-ed memory. The GC will now
+ call the static destroy method rather than the virtual destructor.
+
+ As we go through the hierarchy and add static destroy functions to classes,
+ we will also add a new assert, ASSERT_HAS_TRIVIAL_DESTRUCTOR, to those classes
+ to which it applies. The future goal is to eventually have every class have that assert.
+
+ * API/JSCallbackConstructor.cpp:
+ (JSC::JSCallbackConstructor::destroy): Add a destroy function to statically call
+ ~JSCallbackConstructor because it has some extra destruction logic.
+ * API/JSCallbackConstructor.h:
+ * API/JSCallbackFunction.cpp: Add trivial destructor assert for JSCallbackFunction.
+ * API/JSCallbackObject.cpp: Add a destroy function to statically call ~JSCallbackObject
+ because it has a member OwnPtr that needs destruction.
+ (JSC::::destroy):
+ * API/JSCallbackObject.h:
+ * JavaScriptCore.exp: Add/remove necessary symbols for JSC.
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Same for Windows symbols.
+ * debugger/DebuggerActivation.cpp: DebuggerActivation, for some strange reason, didn't
+ have its own ClassInfo despite the fact that it overrides a number of MethodTable
+ methods. Added the ClassInfo, along with an assertion that its destructor is trivial.
+ * debugger/DebuggerActivation.h:
+ * dfg/DFGOperations.cpp: Remove global data first argument to isJSArray, isJSByteArray,
+ isJSString, as it is no longer necessary.
+ (JSC::DFG::putByVal):
+ * dfg/DFGRepatch.cpp: Ditto. Also remove uses of jsArrayVPtr in favor of using the
+ JSArray ClassInfo pointer.
+ (JSC::DFG::tryCacheGetByID):
+ * dfg/DFGSpeculativeJIT.cpp: Replace uses of the old vptrs with new ClassInfo
+ comparisons since we don't have vptrs anymore.
+ (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality):
+ (JSC::DFG::SpeculativeJIT::compilePeepHoleBranch):
+ (JSC::DFG::SpeculativeJIT::checkArgumentTypes):
+ (JSC::DFG::SpeculativeJIT::compilePutByValForByteArray):
+ (JSC::DFG::SpeculativeJIT::compileGetTypedArrayLength):
+ (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
+ (JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):
+ (JSC::DFG::SpeculativeJIT::compare):
+ (JSC::DFG::SpeculativeJIT::compileStrictEq):
+ (JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
+ * dfg/DFGSpeculativeJIT.h: Ditto.
+ (JSC::DFG::SpeculativeJIT::emitAllocateJSFinalObject):
+ * dfg/DFGSpeculativeJIT32_64.cpp: Ditto.
+ (JSC::DFG::SpeculativeJIT::compileObjectEquality):
+ (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
+ (JSC::DFG::SpeculativeJIT::compileLogicalNot):
+ (JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
+ (JSC::DFG::SpeculativeJIT::emitBranch):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp: Ditto.
+ (JSC::DFG::SpeculativeJIT::compileObjectEquality):
+ (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
+ (JSC::DFG::SpeculativeJIT::compileLogicalNot):
+ (JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
+ (JSC::DFG::SpeculativeJIT::emitBranch):
+ (JSC::DFG::SpeculativeJIT::compile):
+ * heap/Heap.cpp: Remove all uses of vptrs in GC optimizations and replace them with
+ ClassInfo comparisons.
+ (JSC::Heap::Heap):
+ * heap/MarkStack.cpp: Ditto.
+ (JSC::MarkStackThreadSharedData::markingThreadMain):
+ (JSC::visitChildren):
+ (JSC::SlotVisitor::drain):
+ * heap/MarkStack.h: Ditto.
+ (JSC::MarkStack::MarkStack):
+ * heap/MarkedBlock.cpp: Ditto.
+ (JSC::MarkedBlock::callDestructor):
+ (JSC::MarkedBlock::specializedSweep):
+ * heap/MarkedBlock.h: Ditto.
+ * heap/SlotVisitor.h: Ditto.
+ (JSC::SlotVisitor::SlotVisitor):
+ * heap/VTableSpectrum.cpp: Now that we don't have vptrs, we can't count them.
+ We'll have to rename this class and make it use ClassInfo ptrs in a future patch.
+ (JSC::VTableSpectrum::count):
+ * interpreter/Interpreter.cpp: Remove all global data arguments from isJSArray,
+ etc. functions.
+ (JSC::loadVarargs):
+ (JSC::Interpreter::tryCacheGetByID):
+ (JSC::Interpreter::privateExecute):
+ * jit/JIT.h: Remove vptr argument from emitAllocateBasicJSObject
+ * jit/JITInlineMethods.h: Remove vptr planting, and add ClassInfo planting,
+ remove all vtable related code.
+ (JSC::JIT::emitLoadCharacterString):
+ (JSC::JIT::emitAllocateBasicJSObject):
+ (JSC::JIT::emitAllocateJSFinalObject):
+ (JSC::JIT::emitAllocateJSFunction):
+ * jit/JITOpcodes.cpp: Replace vptr related branch code with corresponding ClassInfo.
+ (JSC::JIT::privateCompileCTIMachineTrampolines):
+ (JSC::JIT::emit_op_to_primitive):
+ (JSC::JIT::emit_op_convert_this):
+ * jit/JITOpcodes32_64.cpp: Ditto.
+ (JSC::JIT::privateCompileCTIMachineTrampolines):
+ (JSC::JIT::emit_op_to_primitive):
+ (JSC::JIT::emitSlow_op_eq):
+ (JSC::JIT::emitSlow_op_neq):
+ (JSC::JIT::compileOpStrictEq):
+ (JSC::JIT::emit_op_convert_this):
+ * jit/JITPropertyAccess.cpp: Ditto.
+ (JSC::JIT::stringGetByValStubGenerator):
+ (JSC::JIT::emit_op_get_by_val):
+ (JSC::JIT::emitSlow_op_get_by_val):
+ (JSC::JIT::emit_op_put_by_val):
+ (JSC::JIT::privateCompilePutByIdTransition):
+ (JSC::JIT::privateCompilePatchGetArrayLength):
+ * jit/JITPropertyAccess32_64.cpp: Ditto.
+ (JSC::JIT::stringGetByValStubGenerator):
+ (JSC::JIT::emit_op_get_by_val):
+ (JSC::JIT::emitSlow_op_get_by_val):
+ (JSC::JIT::emit_op_put_by_val):
+ (JSC::JIT::privateCompilePatchGetArrayLength):
+ * jit/JITStubs.cpp: Remove global data argument from isJSString, etc.
+ (JSC::JITThunks::tryCacheGetByID):
+ (JSC::DEFINE_STUB_FUNCTION):
+ * jit/SpecializedThunkJIT.h: Replace vptr related stuff with ClassInfo stuff.
+ (JSC::SpecializedThunkJIT::loadJSStringArgument):
+ * runtime/ArrayConstructor.cpp: Add trivial destructor assert.
+ * runtime/ArrayPrototype.cpp: Remove global data argument from isJSArray.
+ (JSC::arrayProtoFuncToString):
+ (JSC::arrayProtoFuncJoin):
+ (JSC::arrayProtoFuncPop):
+ (JSC::arrayProtoFuncPush):
+ (JSC::arrayProtoFuncShift):
+ (JSC::arrayProtoFuncSplice):
+ (JSC::arrayProtoFuncUnShift):
+ (JSC::arrayProtoFuncFilter):
+ (JSC::arrayProtoFuncMap):
+ (JSC::arrayProtoFuncEvery):
+ (JSC::arrayProtoFuncForEach):
+ (JSC::arrayProtoFuncSome):
+ (JSC::arrayProtoFuncReduce):
+ (JSC::arrayProtoFuncReduceRight):
+ * runtime/BooleanConstructor.cpp: Add trivial destructor assert.
+ * runtime/BooleanObject.cpp: Ditto.
+ * runtime/BooleanPrototype.cpp: Ditto.
+ * runtime/ClassInfo.h: Add destroy function pointer to MethodTable.
+ * runtime/DateConstructor.cpp: Add trivial destructor assert.
+ * runtime/DateInstance.cpp: Add destroy function for DateInstance because it has a RefPtr
+ that needs destruction.
+ (JSC::DateInstance::destroy):
+ * runtime/DateInstance.h:
+ * runtime/Error.cpp: Ditto (because of UString member).
+ (JSC::StrictModeTypeErrorFunction::destroy):
+ * runtime/Error.h:
+ * runtime/ErrorConstructor.cpp: Add trivial destructor assert.
+ * runtime/ErrorInstance.cpp: Ditto.
+ * runtime/ExceptionHelpers.cpp: Ditto.
+ * runtime/Executable.cpp: Add destroy functions for ExecutableBase and subclasses.
+ (JSC::ExecutableBase::destroy):
+ (JSC::NativeExecutable::destroy):
+ (JSC::ScriptExecutable::destroy):
+ (JSC::EvalExecutable::destroy):
+ (JSC::ProgramExecutable::destroy):
+ (JSC::FunctionExecutable::destroy):
+ * runtime/Executable.h:
+ * runtime/FunctionConstructor.cpp: Add trivial destructor assert.
+ * runtime/FunctionPrototype.cpp: Ditto. Also remove global data first arg from isJSArray.
+ (JSC::functionProtoFuncApply):
+ * runtime/GetterSetter.cpp: Ditto.
+ * runtime/InitializeThreading.cpp: Remove call to JSGlobalData::storeVPtrs since it no
+ longer exists.
+ (JSC::initializeThreadingOnce):
+ * runtime/InternalFunction.cpp: Remove vtableAnchor function, add trivial destructor assert,
+ remove first arg from isJSString.
+ (JSC::InternalFunction::displayName):
+ * runtime/InternalFunction.h: Remove VPtrStealingHack.
+ * runtime/JSAPIValueWrapper.cpp: Add trivial destructor assert.
+ * runtime/JSArray.cpp: Add static destroy to call ~JSArray. Replace vptr checks in
+ destructor with ClassInfo checks.
+ (JSC::JSArray::~JSArray):
+ (JSC::JSArray::destroy):
+ * runtime/JSArray.h: Remove VPtrStealingHack. Remove globalData argument from isJSArray
+ and change them to check the ClassInfo rather than the vptrs.
+ (JSC::isJSArray):
+ * runtime/JSBoundFunction.cpp: Add trival destructor assert. Remove first arg from isJSArray.
+ (JSC::boundFunctionCall):
+ (JSC::boundFunctionConstruct):
+ * runtime/JSByteArray.cpp: Add static destroy function, replace vptr checks with ClassInfo checks.
+ (JSC::JSByteArray::~JSByteArray):
+ (JSC::JSByteArray::destroy):
+ * runtime/JSByteArray.h: Remove VPtrStealingHack code.
+ (JSC::isJSByteArray):
+ * runtime/JSCell.cpp: Add trivial destructor assert. Add static destroy function.
+ (JSC::JSCell::destroy):
+ * runtime/JSCell.h: Remove VPtrStealingHack code. Add function for returning the offset
+ of the ClassInfo pointer in the object for use by the JIT. Add the ClassInfo pointer to
+ the JSCell itself, and grab it from the Structure. Remove the vptr and setVPtr functions,
+ as they are no longer used. Add a validatedClassInfo function to JSCell for any clients
+ that want to verify, while in Debug mode, that the ClassInfo contained in the cell is the
+ same one as that contained in the Structure. This isn't used too often, because most of
+ the places where we compare the ClassInfo to things can be called during destruction.
+ Since the Structure is unreliable during the phase when destructors are being called,
+ we can't call validatedClassInfo.
+ (JSC::JSCell::classInfoOffset):
+ (JSC::JSCell::structure):
+ (JSC::JSCell::classInfo):
+ * runtime/JSFunction.cpp: Remove VPtrStealingHack code. Add static destroy, remove vtableAnchor,
+ remove first arg from call to isJSString.
+ (JSC::JSFunction::destroy):
+ (JSC::JSFunction::displayName):
+ * runtime/JSFunction.h:
+ * runtime/JSGlobalData.cpp: Remove all VPtr stealing code and storage, including storeVPtrs,
+ as these vptrs are no longer needed in the codebase.
+ * runtime/JSGlobalData.h:
+ (JSC::TypedArrayDescriptor::TypedArrayDescriptor): Changed the TypedArrayDescriptor to use
+ ClassInfo rather than the vptr.
+ * runtime/JSGlobalObject.cpp: Add static destroy function.
+ (JSC::JSGlobalObject::destroy):
+ * runtime/JSGlobalObject.h:
+ * runtime/JSGlobalThis.cpp: Add trivial destructor assert.
+ * runtime/JSNotAnObject.cpp: Ditto.
+ * runtime/JSONObject.cpp: Ditto. Remove first arg from isJSArray calls.
+ (JSC::Stringifier::Holder::appendNextProperty):
+ (JSC::Walker::walk):
+ * runtime/JSObject.cpp:
+ (JSC::JSFinalObject::destroy):
+ (JSC::JSNonFinalObject::destroy):
+ (JSC::JSObject::destroy):
+ * runtime/JSObject.h: Add trivial destructor assert for JSObject, remove vtableAnchor
+ from JSNonFinalObject and JSFinalObject, add static destroy for JSFinalObject and
+ JSNonFinalObject, add isJSFinalObject utility function similar to isJSArray, remove all VPtrStealingHack code.
+ (JSC::JSObject::finishCreation):
+ (JSC::JSNonFinalObject::finishCreation):
+ (JSC::JSFinalObject::finishCreation):
+ (JSC::isJSFinalObject):
+ * runtime/JSPropertyNameIterator.cpp: Add static destroy.
+ (JSC::JSPropertyNameIterator::destroy):
+ * runtime/JSPropertyNameIterator.h:
+ * runtime/JSStaticScopeObject.cpp: Ditto.
+ (JSC::JSStaticScopeObject::destroy):
+ * runtime/JSStaticScopeObject.h: Ditto.
+ * runtime/JSString.cpp:
+ (JSC::JSString::destroy):
+ * runtime/JSString.h: Ditto. Remove VPtrStealingHack code. Also remove fixupVPtr code,
+ since we no longer need to fixup vptrs.
+ (JSC::jsSingleCharacterString):
+ (JSC::jsSingleCharacterSubstring):
+ (JSC::jsNontrivialString):
+ (JSC::jsString):
+ (JSC::jsSubstring8):
+ (JSC::jsSubstring):
+ (JSC::jsOwnedString):
+ (JSC::jsStringBuilder):
+ (JSC::isJSString):
+ * runtime/JSVariableObject.cpp:
+ (JSC::JSVariableObject::destroy):
+ * runtime/JSVariableObject.h: Ditto.
+ * runtime/JSWrapperObject.cpp:
+ * runtime/JSWrapperObject.h: Add trivial destructor assert.
+ * runtime/MathObject.cpp: Ditto.
+ * runtime/NativeErrorConstructor.cpp: Ditto.
+ * runtime/NumberConstructor.cpp: Ditto.
+ * runtime/NumberObject.cpp: Ditto.
+ * runtime/NumberPrototype.cpp: Ditto.
+ * runtime/ObjectConstructor.cpp: Ditto.
+ * runtime/ObjectPrototype.cpp: Ditto.
+ * runtime/Operations.h: Remove calls to fixupVPtr, remove first arg to isJSString.
+ (JSC::jsString):
+ (JSC::jsLess):
+ (JSC::jsLessEq):
+ * runtime/RegExp.cpp: Add static destroy.
+ (JSC::RegExp::destroy):
+ * runtime/RegExp.h:
+ * runtime/RegExpConstructor.cpp: Add static destroy for RegExpConstructor and RegExpMatchesArray.
+ (JSC::RegExpConstructor::destroy):
+ (JSC::RegExpMatchesArray::destroy):
+ * runtime/RegExpConstructor.h:
+ * runtime/RegExpMatchesArray.h:
+ * runtime/RegExpObject.cpp: Add static destroy.
+ (JSC::RegExpObject::destroy):
+ * runtime/RegExpObject.h:
+ * runtime/ScopeChain.cpp: Add trivial destructor assert.
+ * runtime/ScopeChain.h:
+ * runtime/StrictEvalActivation.cpp: Ditto.
+ * runtime/StringConstructor.cpp:
+ * runtime/StringObject.cpp: Ditto. Remove vtableAnchor.
+ * runtime/StringObject.h:
+ * runtime/StringPrototype.cpp: Ditto.
+ * runtime/Structure.cpp: Add static destroy.
+ (JSC::Structure::destroy):
+ * runtime/Structure.h: Move JSCell::finishCreation and JSCell constructor into Structure.h
+ because they need to have the full Structure type to access the ClassInfo to store in the JSCell.
+ (JSC::JSCell::setStructure):
+ (JSC::JSCell::validatedClassInfo):
+ (JSC::JSCell::JSCell):
+ (JSC::JSCell::finishCreation):
+ * runtime/StructureChain.cpp: Add static destroy.
+ (JSC::StructureChain::destroy):
+ * runtime/StructureChain.h:
+ * wtf/Assertions.h: Add new assertion ASSERT_HAS_TRIVIAL_DESTRUCTOR, which uses clangs
+ ability to tell us when a class has a trivial destructor. We will use this assert
+ more in future patches as we move toward having all JSC objects backed by GC memory,
+ which means moving away from using destructors/finalizers.
+
2011-12-15 Martin Robinson <mrobinson@igalia.com>
Fix 'make dist' in preparation for the GTK+ release.
__ZN3JSC11JSByteArray25getOwnPropertySlotByIndexEPNS_6JSCellEPNS_9ExecStateEjRNS_12PropertySlotE
__ZN3JSC11JSByteArray3putEPNS_6JSCellEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
__ZN3JSC11JSByteArray6s_infoE
+__ZN3JSC11JSByteArray7destroyEPNS_6JSCellE
__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEPNS_9StructureEPN3WTF9ByteArrayE
__ZN3JSC11ParserArena5resetEv
__ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeEPNS_7JSValueE
__ZN3JSC12DateInstance6s_infoE
__ZN3JSC12DateInstanceC1EPNS_9ExecStateEPNS_9StructureE
__ZN3JSC12JSGlobalData10ClientDataD2Ev
-__ZN3JSC12JSGlobalData11jsArrayVPtrE
__ZN3JSC12JSGlobalData12createLeakedENS_15ThreadStackTypeENS_8HeapSizeE
-__ZN3JSC12JSGlobalData12jsStringVPtrE
__ZN3JSC12JSGlobalData12stopSamplingEv
__ZN3JSC12JSGlobalData13startSamplingEv
__ZN3JSC12JSGlobalData14dumpSampleDataEPNS_9ExecStateE
-__ZN3JSC12JSGlobalData14jsFunctionVPtrE
__ZN3JSC12JSGlobalData14resetDateCacheEv
__ZN3JSC12JSGlobalData14sharedInstanceEv
__ZN3JSC12JSGlobalData15dumpRegExpTraceEv
__ZN3JSC14JSGlobalObject3putEPNS_6JSCellEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
__ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
__ZN3JSC14JSGlobalObject6s_infoE
+__ZN3JSC14JSGlobalObject7destroyEPNS_6JSCellE
__ZN3JSC14JSGlobalObjectD2Ev
__ZN3JSC14MachineThreads16addCurrentThreadEv
__ZN3JSC14MarkStackArray6expandEv
__ZN3JSC15WeakHandleOwner8finalizeENS_6HandleINS_7UnknownEEEPv
__ZN3JSC15WeakHandleOwnerD2Ev
__ZN3JSC15createTypeErrorEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC16InternalFunction12vtableAnchorEv
__ZN3JSC16InternalFunction14finishCreationERNS_12JSGlobalDataERKNS_10IdentifierE
__ZN3JSC16InternalFunction4nameEPNS_9ExecStateE
__ZN3JSC16InternalFunction6s_infoE
__ZN3JSC16InternalFunctionC2EPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC16JSNonFinalObject7destroyEPNS_6JSCellE
__ZN3JSC16JSVariableObject14deletePropertyEPNS_6JSCellEPNS_9ExecStateERKNS_10IdentifierE
__ZN3JSC16JSVariableObject14symbolTableGetERKNS_10IdentifierERNS_18PropertyDescriptorE
__ZN3JSC16JSVariableObject19getOwnPropertyNamesEPNS_8JSObjectEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC16JSVariableObject7destroyEPNS_6JSCellE
__ZN3JSC16createRangeErrorEPNS_9ExecStateERKNS_7UStringE
__ZN3JSC16slowValidateCellEPNS_14JSGlobalObjectE
__ZN3JSC16slowValidateCellEPNS_6JSCellE
__ZN3JSC17PropertyNameArray3addEPN3WTF10StringImplE
__ZN3JSC17createSyntaxErrorEPNS_9ExecStateERKNS_7UStringE
__ZN3JSC18DebuggerActivation14finishCreationERNS_12JSGlobalDataEPNS_8JSObjectE
+__ZN3JSC18DebuggerActivation6s_infoE
__ZN3JSC18DebuggerActivationC1ERNS_12JSGlobalDataE
__ZN3JSC18PropertyDescriptor11setWritableEb
__ZN3JSC18PropertyDescriptor12setUndefinedEv
__ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
__ZN3JSC6JSCell11getCallDataEPS0_RNS_8CallDataE
__ZN3JSC6JSCell16getConstructDataEPS0_RNS_13ConstructDataE
+__ZN3JSC6JSCell7destroyEPS0_
__ZN3JSC6JSCell9getObjectEv
__ZN3JSC6JSLock12DropAllLocksC1ENS_14JSLockBehaviorE
__ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
__ZN3JSC6JSLockC1EPNS_9ExecStateE
__ZN3JSC6RegExp5matchERNS_12JSGlobalDataERKNS_7UStringEiPN3WTF6VectorIiLm32EEE
__ZN3JSC6RegExp6createERNS_12JSGlobalDataERKNS_7UStringENS_11RegExpFlagsE
-__ZN3JSC6RegExpD1Ev
__ZN3JSC7JSArray13visitChildrenEPNS_6JSCellERNS_11SlotVisitorE
__ZN3JSC7JSArray14finishCreationERNS_12JSGlobalDataE
__ZN3JSC7JSArray14finishCreationERNS_12JSGlobalDataERKNS_7ArgListE
__ZN3JSC7JSArray15setSubclassDataEPv
__ZN3JSC7JSArray25getOwnPropertySlotByIndexEPNS_6JSCellEPNS_9ExecStateEjRNS_12PropertySlotE
__ZN3JSC7JSArray6s_infoE
+__ZN3JSC7JSArray7destroyEPNS_6JSCellE
__ZN3JSC7JSArray9setLengthEj
__ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureE
__ZN3JSC7JSArrayC2ERNS_12JSGlobalDataEPNS_9StructureE
__ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
__ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
__ZN3JSC8JSObject12toThisObjectEPNS_6JSCellEPNS_9ExecStateE
-__ZN3JSC8JSObject12vtableAnchorEv
__ZN3JSC8JSObject13visitChildrenEPNS_6JSCellERNS_11SlotVisitorE
__ZN3JSC8JSObject14deletePropertyEPNS_6JSCellEPNS_9ExecStateERKNS_10IdentifierE
__ZN3JSC8JSObject16getPropertyNamesEPS0_PNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
__ZN3JSC8JSObject25getOwnPropertySlotByIndexEPNS_6JSCellEPNS_9ExecStateEjRNS_12PropertySlotE
__ZN3JSC8JSObject3putEPNS_6JSCellEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
__ZN3JSC8JSObject6s_infoE
+__ZN3JSC8JSObject7destroyEPNS_6JSCellE
__ZN3JSC8JSObject9classNameEPKS0_
__ZN3JSC8JSString6s_infoE
__ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE
__ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
__ZN3JSC9Structure6s_infoE
__ZN3JSC9StructureC1ERNS_12JSGlobalDataEPNS_14JSGlobalObjectENS_7JSValueERKNS_8TypeInfoEPKNS_9ClassInfoE
-__ZN3JSC9StructureD1Ev
__ZN3JSC9constructEPNS_9ExecStateENS_7JSValueENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
__ZN3JSCeqERKNS_7UStringEPKc
__ZN3JSCgtERKNS_7UStringES2_
__ZNK3WTF6String8toUInt64EPb
__ZNK3WTF6String9substringEjj
__ZNK3WTF8Collator7collateEPKtmS2_m
-__ZTVN3JSC12StringObjectE
-__ZTVN3JSC13JSFinalObjectE
-__ZTVN3JSC14JSGlobalObjectE
-__ZTVN3JSC14ScopeChainNodeE
-__ZTVN3JSC15JSWrapperObjectE
__ZTVN3JSC15WeakHandleOwnerE
-__ZTVN3JSC16InternalFunctionE
-__ZTVN3JSC16JSVariableObjectE
__ZTVN3JSC8DebuggerE
-__ZTVN3JSC8JSObjectE
-__ZTVN3JSC8JSStringE
_jscore_fastmalloc_introspection
_kJSClassDefinitionEmpty
??1Debugger@JSC@@UAE@XZ
??1DropAllLocks@JSLock@JSC@@QAE@XZ
??1JSGlobalData@JSC@@QAE@XZ
- ??1JSGlobalObject@JSC@@UAE@XZ
- ??1JSVariableObject@JSC@@UAE@XZ
+ ??1JSGlobalObject@JSC@@QAE@XZ
??1Mutex@WTF@@QAE@XZ
??1RefCountedLeakCounter@WTF@@QAE@XZ
- ??1ScopeChainNode@JSC@@EAE@XZ
??1SourceProviderCache@JSC@@QAE@XZ
??1ThreadCondition@WTF@@QAE@XZ
??1WTFThreadData@WTF@@QAE@XZ
?despecifyDictionaryFunction@Structure@JSC@@QAEXAAVJSGlobalData@2@ABVIdentifier@2@@Z
?despecifyFunctionTransition@Structure@JSC@@SAPAV12@AAVJSGlobalData@2@PAV12@ABVIdentifier@2@@Z
?destroy@Heap@JSC@@QAEXXZ
+ ?destroy@JSByteArray@JSC@@SAXPAVJSCell@2@@Z
+ ?destroy@JSGlobalObject@JSC@@SAXPAVJSCell@2@@Z
+ ?destroy@JSNonFinalObject@JSC@@SAXPAVJSCell@2@@Z
?detach@Debugger@JSC@@UAEXPAVJSGlobalObject@2@@Z
?detachThread@WTF@@YAXI@Z
?didTimeOut@TimeoutChecker@JSC@@QAE_NPAVExecState@2@@Z
?visitChildren@JSGlobalObject@JSC@@SAXPAVJSCell@2@AAVSlotVisitor@2@@Z
?visitChildren@JSGlobalThis@JSC@@KAXPAVJSCell@2@AAVSlotVisitor@2@@Z
?visitChildren@JSObject@JSC@@SAXPAVJSCell@2@AAVSlotVisitor@2@@Z
- ?vtableAnchor@InternalFunction@JSC@@EAEXXZ
- ?vtableAnchor@JSFinalObject@JSC@@EAEXXZ
- ?vtableAnchor@JSObject@JSC@@UAEXXZ
?wait@ThreadCondition@WTF@@QAEXAAVMutex@2@@Z
?waitForThreadCompletion@WTF@@YAHIPAPAX@Z
?writable@PropertyDescriptor@JSC@@QBE_NXZ
namespace JSC {
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(DebuggerActivation);
+
+const ClassInfo DebuggerActivation::s_info = { "DebuggerActivation", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(DebuggerActivation) };
+
DebuggerActivation::DebuggerActivation(JSGlobalData& globalData)
: JSNonFinalObject(globalData, globalData.debuggerActivationStructure.get())
{
static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes);
static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes);
+ static const ClassInfo s_info;
+
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
{
return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
{
JSGlobalData* globalData = &exec->globalData();
- if (isJSArray(globalData, baseValue)) {
+ if (isJSArray(baseValue)) {
JSArray* array = asArray(baseValue);
if (array->canSetIndex(index)) {
array->setIndex(*globalData, index, value);
return;
}
- if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(index)) {
+ if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(index)) {
JSByteArray* byteArray = asByteArray(baseValue);
// FIXME: the JITstub used to relink this to an optimized form!
if (value.isInt32()) {
static inline EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
{
- JSGlobalData* globalData = &exec->globalData();
-
// FIXME: the JIT used to handle these in compiled code!
- if (isJSArray(globalData, base) && asArray(base)->canGetIndex(index))
+ if (isJSArray(base) && asArray(base)->canGetIndex(index))
return JSValue::encode(asArray(base)->getIndex(index));
// FIXME: the JITstub used to relink this to an optimized form!
- if (isJSString(globalData, base) && asString(base)->canGetIndex(index))
+ if (isJSString(base) && asString(base)->canGetIndex(index))
return JSValue::encode(asString(base)->getIndex(exec, index));
// FIXME: the JITstub used to relink this to an optimized form!
- if (isJSByteArray(globalData, base) && asByteArray(base)->canAccessIndex(index))
+ if (isJSByteArray(base) && asByteArray(base)->canAccessIndex(index))
return JSValue::encode(asByteArray(base)->getIndex(exec, index));
return JSValue::encode(JSValue(base).get(exec, index));
CodeBlock* codeBlock = exec->codeBlock();
JSGlobalData* globalData = &exec->globalData();
- if (isJSArray(globalData, baseValue) && propertyName == exec->propertyNames().length) {
+ if (isJSArray(baseValue) && propertyName == exec->propertyNames().length) {
GPRReg baseGPR = static_cast<GPRReg>(stubInfo.baseGPR);
#if USE(JSVALUE32_64)
GPRReg resultTagGPR = static_cast<GPRReg>(stubInfo.valueTagGPR);
MacroAssembler::JumpList failureCases;
- failureCases.append(stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(globalData->jsArrayVPtr)));
+ failureCases.append(stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), scratchGPR);
stubJit.load32(MacroAssembler::Address(scratchGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), scratchGPR);
addBranch(m_jit.jump(), notTaken);
}
-void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, void* vptr, PredictionChecker predictionCheck)
+void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, const ClassInfo* classInfo, PredictionChecker predictionCheck)
{
Node& branchNode = at(branchNodeIndex);
BlockIndex taken = branchNode.takenBlockIndex();
GPRReg op2GPR = op2.gpr();
if (!predictionCheck(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
if (!predictionCheck(m_state.forNode(node.child2()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
addBranch(m_jit.branchPtr(condition, op1GPR, op2GPR), taken);
if (notTaken != (m_block + 1))
use(node.child1());
use(node.child2());
} else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
- compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsFinalObjectVPtr, isFinalObjectPrediction);
+ compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction);
use(node.child1());
use(node.child2());
} else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
- compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsArrayVPtr, isArrayPrediction);
+ compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction);
use(node.child1());
use(node.child2());
} else
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
} else if (isByteArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsByteArrayVPtr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
} else if (isBooleanPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
} else if (isInt16ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
} else if (isInt32ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
} else if (isUint8ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
} else if (isUint16ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
} else if (isUint32ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
} else if (isFloat32ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
} else if (isFloat64ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
}
#else
if (isInt32Prediction(predictedType))
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
} else if (isByteArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsByteArrayVPtr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
} else if (isBooleanPrediction(predictedType))
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
else if (isInt8ArrayPrediction(predictedType)) {
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
} else if (isInt16ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
} else if (isInt32ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
} else if (isUint8ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
} else if (isUint16ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
} else if (isUint32ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
} else if (isFloat32ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
} else if (isFloat64ArrayPrediction(predictedType)) {
GPRTemporary temp(this);
m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
- speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_vptr)));
+ speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
}
#endif
}
NodeIndex valueIndex = node.child3();
if (!isByteArrayPrediction(m_state.forNode(baseIndex).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsByteArrayVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
GPRTemporary value;
GPRReg valueGPR;
GPRReg resultGPR = result.gpr();
if (needsSpeculationCheck)
- speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(descriptor.m_vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.load32(MacroAssembler::Address(baseGPR, descriptor.m_lengthOffset), resultGPR);
NodeIndex valueIndex = node.child3();
if (speculationRequirements != NoTypedArrayTypeSpecCheck)
- speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base), MacroAssembler::TrustedImmPtr(descriptor.m_vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
GPRTemporary value;
GPRReg valueGPR;
SpeculateDoubleOperand valueOp(this, valueIndex);
if (speculationRequirements != NoTypedArrayTypeSpecCheck)
- speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base), MacroAssembler::TrustedImmPtr(descriptor.m_vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
GPRTemporary result(this);
else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2())))
compileDoubleCompare(node, doubleCondition);
else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2())))
- compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr, isFinalObjectPrediction);
+ compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2())))
- compileObjectEquality(node, m_jit.globalData()->jsArrayVPtr, isArrayPrediction);
+ compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
else
nonSpeculativeNonPeepholeCompare(node, condition, operation);
if (Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
NodeIndex branchNodeIndex = detectPeepHoleBranch();
if (branchNodeIndex != NoNode) {
- compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsFinalObjectVPtr, isFinalObjectPrediction);
+ compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction);
use(node.child1());
use(node.child2());
m_compileIndex = branchNodeIndex;
return true;
}
- compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr, isFinalObjectPrediction);
+ compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
return false;
}
if (Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
NodeIndex branchNodeIndex = detectPeepHoleBranch();
if (branchNodeIndex != NoNode) {
- compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsArrayVPtr, isArrayPrediction);
+ compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction);
use(node.child1());
use(node.child2());
m_compileIndex = branchNodeIndex;
return true;
}
- compileObjectEquality(node, m_jit.globalData()->jsArrayVPtr, isArrayPrediction);
+ compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
return false;
}
GPRReg storageReg = storage.gpr();
if (at(node.child1()).prediction() == PredictString) {
if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), storageReg);
m_jit.loadPtr(MacroAssembler::Address(storageReg, StringImpl::dataOffset()), storageReg);
} else if (at(node.child1()).shouldSpeculateByteArray()) {
if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsByteArrayVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, JSByteArray::offsetOfStorage()), storageReg);
} else if (at(node.child1()).shouldSpeculateInt8Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->int8ArrayDescriptor();
if (!isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateInt16Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->int16ArrayDescriptor();
if (!isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateInt32Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->int32ArrayDescriptor();
if (!isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateUint8Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ArrayDescriptor();
if (!isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateUint16Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint16ArrayDescriptor();
if (!isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateUint32Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint32ArrayDescriptor();
if (!isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateFloat32Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->float32ArrayDescriptor();
if (!isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else if (at(node.child1()).shouldSpeculateFloat64Array()) {
const TypedArrayDescriptor& descriptor = m_jit.globalData()->float64ArrayDescriptor();
if (!isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
} else {
if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
}
storageResult(storageReg, m_compileIndex);
bool compilePeepHoleBranch(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ);
void compilePeepHoleIntegerBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition);
void compilePeepHoleDoubleBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition);
- void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, void* vptr, PredictionChecker);
- void compileObjectEquality(Node&, void* vptr, PredictionChecker);
+ void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, const ClassInfo*, PredictionChecker);
+ void compileObjectEquality(Node&, const ClassInfo*, PredictionChecker);
void compileValueAdd(Node&);
- void compileObjectOrOtherLogicalNot(NodeIndex value, void* vptr, bool needSpeculationCheck);
+ void compileObjectOrOtherLogicalNot(NodeIndex value, const ClassInfo*, bool needSpeculationCheck);
void compileLogicalNot(Node&);
- void emitObjectOrOtherBranch(NodeIndex value, BlockIndex taken, BlockIndex notTaken, void *vptr, bool needSpeculationCheck);
+ void emitObjectOrOtherBranch(NodeIndex value, BlockIndex taken, BlockIndex notTaken, const ClassInfo*, bool needSpeculationCheck);
void emitBranch(Node&);
void compileIntegerCompare(Node&, MacroAssembler::RelationalCondition);
m_jit.loadPtr(MacroAssembler::Address(resultGPR), scratchGPR);
m_jit.storePtr(scratchGPR, &sizeClass->firstFreeCell);
- // Initialize the object's vtable
- m_jit.storePtr(MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr), MacroAssembler::Address(resultGPR));
+ // Initialize the object's classInfo pointer
+ m_jit.storePtr(MacroAssembler::TrustedImmPtr(&JSFinalObject::s_info), MacroAssembler::Address(resultGPR, JSCell::classInfoOffset()));
// Initialize the object's inheritorID.
m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::Address(resultGPR, JSObject::offsetOfInheritorID()));
return notNumber;
}
-void SpeculativeJIT::compileObjectEquality(Node& node, void* vptr, PredictionChecker predictionCheck)
+void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInfo, PredictionChecker predictionCheck)
{
SpeculateCellOperand op1(this, node.child1());
SpeculateCellOperand op2(this, node.child2());
GPRReg resultPayloadGPR = resultPayload.gpr();
if (!predictionCheck(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
if (!predictionCheck(m_state.forNode(node.child2()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
m_jit.move(Imm32(1), resultPayloadGPR);
jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
}
-void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, void* vptr, bool needSpeculationCheck)
+void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, const ClassInfo* classInfo, bool needSpeculationCheck)
{
JSValueOperand value(this, nodeIndex);
GPRTemporary resultPayload(this);
MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag));
if (needSpeculationCheck)
- speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR), MacroAssembler::TrustedImmPtr(vptr)));
+ speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
m_jit.move(TrustedImm32(0), resultPayloadGPR);
MacroAssembler::Jump done = m_jit.jump();
return;
}
if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
- compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsFinalObjectVPtr, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ compileObjectOrOtherLogicalNot(node.child1(), &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
return;
}
if (at(node.child1()).shouldSpeculateArrayOrOther()) {
- compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsArrayVPtr, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ compileObjectOrOtherLogicalNot(node.child1(), &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
return;
}
if (at(node.child1()).shouldSpeculateInteger()) {
booleanResult(resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
}
-void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, void *vptr, bool needSpeculationCheck)
+void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, const ClassInfo* classInfo, bool needSpeculationCheck)
{
JSValueOperand value(this, nodeIndex);
GPRTemporary scratch(this);
MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag));
if (needSpeculationCheck)
- speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR), MacroAssembler::TrustedImmPtr(vptr)));
+ speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
addBranch(m_jit.jump(), taken);
notCell.link(&m_jit);
noResult(m_compileIndex);
} else if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
- emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsFinalObjectVPtr, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
} else if (at(node.child1()).shouldSpeculateArrayOrOther()) {
- emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsArrayVPtr, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
} else if (at(node.child1()).shouldSpeculateNumber()) {
if (at(node.child1()).shouldSpeculateInteger()) {
bool invert = false;
SpeculateCellOperand cell(this, node.child1());
GPRReg cellGPR = cell.gpr();
if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
} else if (isByteArrayPrediction(predictedType)) {
SpeculateCellOperand cell(this, node.child1());
GPRReg cellGPR = cell.gpr();
if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsByteArrayVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local()));
noResult(m_compileIndex);
} else if (isBooleanPrediction(predictedType)) {
SpeculateCellOperand base(this, node.child1());
GPRReg baseReg = base.gpr();
if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
}
// Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
// If we have predicted the base to be type array, we can skip the check.
if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
base.use();
property.use();
writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
GPRReg storageLengthGPR = storageLength.gpr();
if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
MacroAssembler::JumpList alreadyPrimitive;
alreadyPrimitive.append(m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, TrustedImm32(JSValue::CellTag)));
- alreadyPrimitive.append(m_jit.branchPtr(MacroAssembler::Equal, MacroAssembler::Address(op1PayloadGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
+ alreadyPrimitive.append(m_jit.branchPtr(MacroAssembler::Equal, MacroAssembler::Address(op1PayloadGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
silentSpillAllRegisters(resultTagGPR, resultPayloadGPR);
callOperation(operationToPrimitive, resultTagGPR, resultPayloadGPR, op1TagGPR, op1PayloadGPR);
GPRReg resultGPR = result.gpr();
if (!isObjectPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::classInfoOffset()), JITCompiler::TrustedImmPtr(&JSString::s_info)));
m_jit.move(thisValueGPR, resultGPR);
cellResult(resultGPR, m_compileIndex);
// do the slow (structure-based) check.
if (at(node.child1()).shouldSpeculateFinalObject()) {
if (!isFinalObjectPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(protoGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(protoGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSFinalObject::s_info)));
} else {
m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
GPRReg resultGPR = result.gpr();
if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR);
m_jit.load32(MacroAssembler::Address(resultGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultGPR);
GPRReg resultGPR = result.gpr();
if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR);
GPRReg resultGPR = result.gpr();
if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsByteArrayVPtr)));
+ speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSByteArray::offsetOfStorage()), resultGPR);
m_jit.load32(MacroAssembler::Address(baseGPR, ByteArray::offsetOfSize()), resultGPR);
return notNumber;
}
-void SpeculativeJIT::compileObjectEquality(Node& node, void* vptr, PredictionChecker predictionCheck)
+void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInfo, PredictionChecker predictionCheck)
{
SpeculateCellOperand op1(this, node.child1());
SpeculateCellOperand op2(this, node.child2());
GPRReg resultGPR = result.gpr();
if (!predictionCheck(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(op1GPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
+ speculationCheck(BadType, JSValueRegs(op1GPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
if (!predictionCheck(m_state.forNode(node.child2()).m_type))
- speculationCheck(BadType, JSValueRegs(op2GPR), node.child2(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
+ speculationCheck(BadType, JSValueRegs(op2GPR), node.child2(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
m_jit.move(Imm32(ValueTrue), resultGPR);
jsValueResult(result.gpr(), m_compileIndex);
}
-void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, void *vptr, bool needSpeculationCheck)
+void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, const ClassInfo* classInfo, bool needSpeculationCheck)
{
JSValueOperand value(this, nodeIndex);
GPRTemporary result(this);
MacroAssembler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
if (needSpeculationCheck)
- speculationCheck(BadType, JSValueRegs(valueGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR), MacroAssembler::TrustedImmPtr(vptr)));
+ speculationCheck(BadType, JSValueRegs(valueGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
m_jit.move(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
MacroAssembler::Jump done = m_jit.jump();
return;
}
if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
- compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsFinalObjectVPtr, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ compileObjectOrOtherLogicalNot(node.child1(), &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
return;
}
if (at(node.child1()).shouldSpeculateArrayOrOther()) {
- compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsArrayVPtr, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ compileObjectOrOtherLogicalNot(node.child1(), &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
return;
}
if (at(node.child1()).shouldSpeculateInteger()) {
jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
}
-void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, void *vptr, bool needSpeculationCheck)
+void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, const ClassInfo* classInfo, bool needSpeculationCheck)
{
JSValueOperand value(this, nodeIndex);
GPRTemporary scratch(this);
MacroAssembler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
if (needSpeculationCheck)
- speculationCheck(BadType, JSValueRegs(valueGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR), MacroAssembler::TrustedImmPtr(vptr)));
+ speculationCheck(BadType, JSValueRegs(valueGPR), nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
addBranch(m_jit.jump(), taken);
notCell.link(&m_jit);
noResult(m_compileIndex);
} else if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
- emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsFinalObjectVPtr, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
} else if (at(node.child1()).shouldSpeculateArrayOrOther()) {
- emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsArrayVPtr, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
+ emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
} else if (at(node.child1()).shouldSpeculateNumber()) {
if (at(node.child1()).shouldSpeculateInteger()) {
bool invert = false;
SpeculateCellOperand cell(this, node.child1());
GPRReg cellGPR = cell.gpr();
if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(BadType, JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
noResult(m_compileIndex);
} else if (isByteArrayPrediction(predictedType)) {
SpeculateCellOperand cell(this, node.child1());
GPRReg cellGPR = cell.gpr();
if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsByteArrayVPtr)));
+ speculationCheck(BadType, JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
noResult(m_compileIndex);
} else if (isBooleanPrediction(predictedType)) {
return;
if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
// FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache
// Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
// If we have predicted the base to be type array, we can skip the check.
if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
base.use();
property.use();
writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
GPRReg storageLengthGPR = storageLength.gpr();
if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
MacroAssembler::JumpList alreadyPrimitive;
alreadyPrimitive.append(m_jit.branchTestPtr(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister));
- alreadyPrimitive.append(m_jit.branchPtr(MacroAssembler::Equal, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
+ alreadyPrimitive.append(m_jit.branchPtr(MacroAssembler::Equal, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
silentSpillAllRegisters(resultGPR);
callOperation(operationToPrimitive, resultGPR, op1GPR);
GPRReg resultGPR = result.gpr();
if (!isObjectPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
+ speculationCheck(BadType, JSValueRegs(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::classInfoOffset()), JITCompiler::TrustedImmPtr(&JSString::s_info)));
m_jit.move(thisValueGPR, resultGPR);
// do the slow (structure-based) check.
if (at(node.child1()).shouldSpeculateFinalObject()) {
if (!isFinalObjectPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(protoGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr)));
+ speculationCheck(BadType, JSValueRegs(protoGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSFinalObject::s_info)));
} else {
m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
GPRReg resultGPR = result.gpr();
if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+ speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR);
m_jit.load32(MacroAssembler::Address(resultGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultGPR);
GPRReg resultGPR = result.gpr();
if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
+ speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR);
GPRReg resultGPR = result.gpr();
if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type))
- speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsByteArrayVPtr)));
+ speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSByteArray::offsetOfStorage()), resultGPR);
m_jit.load32(MacroAssembler::Address(baseGPR, ByteArray::offsetOfSize()), resultGPR);
, m_activityCallback(DefaultGCActivityCallback::create(this))
, m_machineThreads(this)
, m_sharedData(globalData)
- , m_slotVisitor(m_sharedData, globalData->jsArrayVPtr, globalData->jsFinalObjectVPtr, globalData->jsStringVPtr)
+ , m_slotVisitor(m_sharedData)
, m_handleHeap(globalData)
, m_isSafeToCollect(false)
, m_globalData(globalData)
void MarkStackThreadSharedData::markingThreadMain()
{
WTF::registerGCThread();
- SlotVisitor slotVisitor(*this, m_globalData->jsArrayVPtr, m_globalData->jsFinalObjectVPtr, m_globalData->jsStringVPtr);
+ SlotVisitor slotVisitor(*this);
ParallelModeEnabler enabler(slotVisitor);
slotVisitor.drainFromShared(SlotVisitor::SlaveDrain);
}
internalAppend(roots[i]);
}
-ALWAYS_INLINE static void visitChildren(SlotVisitor& visitor, const JSCell* cell, void* jsFinalObjectVPtr, void* jsArrayVPtr, void* jsStringVPtr)
+ALWAYS_INLINE static void visitChildren(SlotVisitor& visitor, const JSCell* cell)
{
#if ENABLE(SIMPLE_HEAP_PROFILING)
m_visitedTypeCounts.count(cell);
ASSERT(Heap::isMarked(cell));
- if (cell->vptr() == jsStringVPtr) {
+ if (isJSString(cell)) {
JSString::visitChildren(const_cast<JSCell*>(cell), visitor);
return;
}
- if (cell->vptr() == jsFinalObjectVPtr) {
+ if (isJSFinalObject(cell)) {
JSObject::visitChildren(const_cast<JSCell*>(cell), visitor);
return;
}
- if (cell->vptr() == jsArrayVPtr) {
+ if (isJSArray(cell)) {
JSArray::visitChildren(const_cast<JSCell*>(cell), visitor);
return;
}
{
ASSERT(m_isInParallelMode);
- void* jsFinalObjectVPtr = m_jsFinalObjectVPtr;
- void* jsArrayVPtr = m_jsArrayVPtr;
- void* jsStringVPtr = m_jsStringVPtr;
-
#if ENABLE(PARALLEL_GC)
if (Options::numberOfGCMarkers > 1) {
while (!m_stack.isEmpty()) {
m_stack.refill();
for (unsigned countdown = Options::minimumNumberOfScansBetweenRebalance; m_stack.canRemoveLast() && countdown--;)
- visitChildren(*this, m_stack.removeLast(), jsFinalObjectVPtr, jsArrayVPtr, jsStringVPtr);
+ visitChildren(*this, m_stack.removeLast());
donateKnownParallel();
}
while (!m_stack.isEmpty()) {
m_stack.refill();
while (m_stack.canRemoveLast())
- visitChildren(*this, m_stack.removeLast(), jsFinalObjectVPtr, jsArrayVPtr, jsStringVPtr);
+ visitChildren(*this, m_stack.removeLast());
}
}
friend class HeapRootVisitor; // Allowed to mark a JSValue* or JSCell** directly.
public:
- MarkStack(MarkStackThreadSharedData&, void* jsArrayVPtr, void* jsFinalObjectVPtr, void* jsStringVPtr);
+ MarkStack(MarkStackThreadSharedData&);
~MarkStack();
void append(ConservativeRoots&);
}
MarkStackArray m_stack;
- void* m_jsArrayVPtr;
- void* m_jsFinalObjectVPtr;
- void* m_jsStringVPtr;
HashSet<void*> m_opaqueRoots; // Handle-owning data structures not visible to the garbage collector.
#if !ASSERT_DISABLED
MarkStackThreadSharedData& m_shared;
};
- inline MarkStack::MarkStack(MarkStackThreadSharedData& shared, void* jsArrayVPtr, void* jsFinalObjectVPtr, void* jsStringVPtr)
+ inline MarkStack::MarkStack(MarkStackThreadSharedData& shared)
: m_stack(shared.m_segmentAllocator)
- , m_jsArrayVPtr(jsArrayVPtr)
- , m_jsFinalObjectVPtr(jsFinalObjectVPtr)
- , m_jsStringVPtr(jsStringVPtr)
#if !ASSERT_DISABLED
, m_isCheckingForDefaultMarkViolation(false)
, m_isDraining(false)
HEAP_LOG_BLOCK_STATE_TRANSITION(this);
}
-inline void MarkedBlock::callDestructor(JSCell* cell, void* jsFinalObjectVPtr)
+inline void MarkedBlock::callDestructor(JSCell* cell)
{
// A previous eager sweep may already have run cell's destructor.
if (cell->isZapped())
return;
- void* vptr = cell->vptr();
#if ENABLE(SIMPLE_HEAP_PROFILING)
m_heap->m_destroyedTypeCounts.countVPtr(vptr);
#endif
- if (vptr != jsFinalObjectVPtr)
- cell->~JSCell();
+ if (cell->classInfo() != &JSFinalObject::s_info)
+ cell->methodTable()->destroy(cell);
cell->zap();
}
// This is fine, since the allocation code makes no assumptions about the
// order of the free list.
FreeCell* head = 0;
- void* jsFinalObjectVPtr = m_heap->globalData()->jsFinalObjectVPtr;
for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
if (blockState == Marked && m_marks.get(i))
continue;
continue;
if (blockState != New)
- callDestructor(cell, jsFinalObjectVPtr);
+ callDestructor(cell);
if (sweepMode == SweepToFreeList) {
FreeCell* freeCell = reinterpret_cast<FreeCell*>(cell);
MarkedBlock(const PageAllocationAligned&, Heap*, size_t cellSize);
Atom* atoms();
size_t atomNumber(const void*);
- void callDestructor(JSCell*, void* jsFinalObjectVPtr);
+ void callDestructor(JSCell*);
template<BlockState, SweepMode> FreeCell* specializedSweep();
#if ENABLE(GGC)
class SlotVisitor : public MarkStack {
friend class HeapRootVisitor;
public:
- SlotVisitor(MarkStackThreadSharedData&, void* jsArrayVPtr, void* jsFinalObjectVPtr, void* jsStringVPtr);
+ SlotVisitor(MarkStackThreadSharedData&);
void donate()
{
}
};
-inline SlotVisitor::SlotVisitor(MarkStackThreadSharedData& shared, void* jsArrayVPtr, void* jsFinalObjectVPtr, void* jsStringVPtr)
- : MarkStack(shared, jsArrayVPtr, jsFinalObjectVPtr, jsStringVPtr)
+inline SlotVisitor::SlotVisitor(MarkStackThreadSharedData& shared)
+ : MarkStack(shared)
{
}
void VTableSpectrum::count(JSCell* cell)
{
- countVPtr(cell->vptr());
+ // FIXME: we need to change this class to count ClassInfos rather than vptrs
+ UNUSED_PARAM(cell);
}
void VTableSpectrum::dump(FILE* output, const char* comment)
return newCallFrame;
}
- if (isJSArray(&callFrame->globalData(), arguments)) {
+ if (isJSArray(arguments)) {
JSArray* array = asArray(arguments);
unsigned argCount = array->length();
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
return;
}
- JSGlobalData* globalData = &callFrame->globalData();
- if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
+ if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
vPC[0] = getOpcode(op_get_array_length);
return;
}
- if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
+ if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
vPC[0] = getOpcode(op_get_string_length);
return;
}
int base = vPC[2].u.operand;
JSValue baseValue = callFrame->r(base).jsValue();
- if (LIKELY(isJSArray(globalData, baseValue))) {
+ if (LIKELY(isJSArray(baseValue))) {
int dst = vPC[1].u.operand;
callFrame->uncheckedR(dst) = jsNumber(asArray(baseValue)->length());
vPC += OPCODE_LENGTH(op_get_array_length);
int base = vPC[2].u.operand;
JSValue baseValue = callFrame->r(base).jsValue();
- if (LIKELY(isJSString(globalData, baseValue))) {
+ if (LIKELY(isJSString(baseValue))) {
int dst = vPC[1].u.operand;
callFrame->uncheckedR(dst) = jsNumber(asString(baseValue)->length());
vPC += OPCODE_LENGTH(op_get_string_length);
if (LIKELY(subscript.isUInt32())) {
uint32_t i = subscript.asUInt32();
- if (isJSArray(globalData, baseValue)) {
+ if (isJSArray(baseValue)) {
JSArray* jsArray = asArray(baseValue);
if (jsArray->canGetIndex(i))
result = jsArray->getIndex(i);
else
result = jsArray->JSArray::get(callFrame, i);
- } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
+ } else if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
result = asString(baseValue)->getIndex(callFrame, i);
- else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i))
+ else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i))
result = asByteArray(baseValue)->getIndex(callFrame, i);
else
result = baseValue.get(callFrame, i);
if (LIKELY(subscript.isUInt32())) {
uint32_t i = subscript.asUInt32();
- if (isJSArray(globalData, baseValue)) {
+ if (isJSArray(baseValue)) {
JSArray* jsArray = asArray(baseValue);
if (jsArray->canSetIndex(i))
jsArray->setIndex(*globalData, i, callFrame->r(value).jsValue());
else
jsArray->JSArray::putByIndex(jsArray, callFrame, i, callFrame->r(value).jsValue());
- } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+ } else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
JSByteArray* jsByteArray = asByteArray(baseValue);
JSValue jsValue = callFrame->r(value).jsValue();
if (jsValue.isInt32())
void emitWriteBarrier(RegisterID owner, RegisterID valueTag, RegisterID scratch, RegisterID scratch2, WriteBarrierMode, WriteBarrierUseKind);
void emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode, WriteBarrierUseKind);
- template<typename ClassType, typename StructureType> void emitAllocateBasicJSObject(StructureType, void* vtable, RegisterID result, RegisterID storagePtr);
+ template<typename ClassType, typename StructureType> void emitAllocateBasicJSObject(StructureType, RegisterID result, RegisterID storagePtr);
template<typename T> void emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID storagePtr);
void emitAllocateJSFunction(FunctionExecutable*, RegisterID scopeChain, RegisterID result, RegisterID storagePtr);
ALWAYS_INLINE void JIT::emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures)
{
- failures.append(branchPtr(NotEqual, Address(src), TrustedImmPtr(m_globalData->jsStringVPtr)));
+ failures.append(branchPtr(NotEqual, Address(src, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
failures.append(branch32(NotEqual, MacroAssembler::Address(src, ThunkHelpers::jsStringLengthOffset()), TrustedImm32(1)));
loadPtr(MacroAssembler::Address(src, ThunkHelpers::jsStringValueOffset()), dst);
failures.append(branchTest32(Zero, dst));
return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isString() && asString(getConstantOperand(src).asCell())->length() == 1;
}
-template <typename ClassType, typename StructureType> inline void JIT::emitAllocateBasicJSObject(StructureType structure, void* vtable, RegisterID result, RegisterID storagePtr)
+template <typename ClassType, typename StructureType> inline void JIT::emitAllocateBasicJSObject(StructureType structure, RegisterID result, RegisterID storagePtr)
{
MarkedSpace::SizeClass* sizeClass = &m_globalData->heap.sizeClassForObject(sizeof(ClassType));
loadPtr(&sizeClass->firstFreeCell, result);
loadPtr(Address(result), storagePtr);
storePtr(storagePtr, &sizeClass->firstFreeCell);
- // initialize the object's vtable
- storePtr(TrustedImmPtr(vtable), Address(result));
-
// initialize the object's structure
storePtr(structure, Address(result, JSCell::structureOffset()));
+ // initialize the object's classInfo pointer
+ storePtr(TrustedImmPtr(&ClassType::s_info), Address(result, JSCell::classInfoOffset()));
+
// initialize the inheritor ID
storePtr(TrustedImmPtr(0), Address(result, JSObject::offsetOfInheritorID()));
template <typename T> inline void JIT::emitAllocateJSFinalObject(T structure, RegisterID result, RegisterID scratch)
{
- emitAllocateBasicJSObject<JSFinalObject>(structure, m_globalData->jsFinalObjectVPtr, result, scratch);
+ emitAllocateBasicJSObject<JSFinalObject>(structure, result, scratch);
}
inline void JIT::emitAllocateJSFunction(FunctionExecutable* executable, RegisterID scopeChain, RegisterID result, RegisterID storagePtr)
{
- emitAllocateBasicJSObject<JSFunction>(TrustedImmPtr(m_codeBlock->globalObject()->namedFunctionStructure()), m_globalData->jsFunctionVPtr, result, storagePtr);
+ emitAllocateBasicJSObject<JSFunction>(TrustedImmPtr(m_codeBlock->globalObject()->namedFunctionStructure()), result, storagePtr);
// store the function's scope chain
storePtr(scopeChain, Address(result, JSFunction::offsetOfScopeChain()));
// Check eax is a string
Jump string_failureCases1 = emitJumpIfNotJSCell(regT0);
- Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr));
+ Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info));
// Checks out okay! - get the length from the Ustring.
load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_length)), regT0);
emitGetVirtualRegister(src, regT0);
Jump isImm = emitJumpIfNotJSCell(regT0);
- addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)));
+ addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
isImm.link(this);
if (dst != src)
emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
emitJumpSlowCaseIfNotJSCell(regT0);
- addSlowCase(branchPtr(Equal, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)));
+ addSlowCase(branchPtr(Equal, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
}
void JIT::emit_op_get_callee(Instruction* currentInstruction)
// regT0 holds payload, regT1 holds tag
Jump string_failureCases1 = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
- Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr));
+ Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info));
// Checks out okay! - get the length from the Ustring.
load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_length)), regT2);
emitLoad(src, regT1, regT0);
Jump isImm = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
- addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)));
+ addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
isImm.link(this);
if (dst != src)
genericCase.append(getSlowCase(iter)); // tags not equal
linkSlowCase(iter); // tags equal and JSCell
- genericCase.append(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)));
- genericCase.append(branchPtr(NotEqual, Address(regT2), TrustedImmPtr(m_globalData->jsStringVPtr)));
+ genericCase.append(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
+ genericCase.append(branchPtr(NotEqual, Address(regT2, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
// String case.
JITStubCall stubCallEqStrings(this, cti_op_eq_strings);
genericCase.append(getSlowCase(iter)); // tags not equal
linkSlowCase(iter); // tags equal and JSCell
- genericCase.append(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)));
- genericCase.append(branchPtr(NotEqual, Address(regT2), TrustedImmPtr(m_globalData->jsStringVPtr)));
+ genericCase.append(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
+ genericCase.append(branchPtr(NotEqual, Address(regT2, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
// String case.
JITStubCall stubCallEqStrings(this, cti_op_eq_strings);
// Jump to a slow case if both are strings.
Jump notCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
- Jump firstNotString = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr));
- addSlowCase(branchPtr(Equal, Address(regT2), TrustedImmPtr(m_globalData->jsStringVPtr)));
+ Jump firstNotString = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info));
+ addSlowCase(branchPtr(Equal, Address(regT2, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
notCell.link(this);
firstNotString.link(this);
emitLoad(thisRegister, regT1, regT0);
addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
- addSlowCase(branchPtr(Equal, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)));
+ addSlowCase(branchPtr(Equal, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
map(m_bytecodeOffset + OPCODE_LENGTH(op_convert_this), thisRegister, regT1, regT0);
}
{
JSInterfaceJIT jit;
JumpList failures;
- failures.append(jit.branchPtr(NotEqual, Address(regT0), TrustedImmPtr(globalData->jsStringVPtr)));
+ failures.append(jit.branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
// Load string length to regT2, and start the process of loading the data pointer into regT0
jit.load32(Address(regT0, ThunkHelpers::jsStringLengthOffset()), regT2);
zeroExtend32ToPtr(regT1, regT1);
emitJumpSlowCaseIfNotJSCell(regT0, base);
- addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)));
+ addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, JSArray::vectorLengthOffset())));
linkSlowCaseIfNotJSCell(iter, base); // base cell check
Jump nonCell = jump();
linkSlowCase(iter); // base array check
- Jump notString = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr));
+ Jump notString = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info));
emitNakedCall(CodeLocationLabel(m_globalData->getCTIStub(stringGetByValStubGenerator).code()));
Jump failed = branchTestPtr(Zero, regT0);
emitPutVirtualRegister(dst, regT0);
// See comment in op_get_by_val.
zeroExtend32ToPtr(regT1, regT1);
emitJumpSlowCaseIfNotJSCell(regT0, base);
- addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)));
+ addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, JSArray::vectorLengthOffset())));
loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
// an unconditional barrier here.
emitWriteBarrier(regT0, regT1, regT2, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess);
+ ASSERT(newStructure->classInfo() == oldStructure->classInfo());
storePtr(TrustedImmPtr(newStructure), Address(regT0, JSCell::structureOffset()));
compilePutDirectOffset(regT0, regT1, cachedOffset);
StructureStubInfo* stubInfo = &m_codeBlock->getStubInfo(returnAddress);
// Check eax is an array
- Jump failureCases1 = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr));
+ Jump failureCases1 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info));
// Checks out okay! - get the length from the storage
loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
{
JSInterfaceJIT jit;
JumpList failures;
- failures.append(jit.branchPtr(NotEqual, Address(regT0), TrustedImmPtr(globalData->jsStringVPtr)));
+ failures.append(jit.branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
// Load string length to regT1, and start the process of loading the data pointer into regT0
jit.load32(Address(regT0, ThunkHelpers::jsStringLengthOffset()), regT1);
addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
emitJumpSlowCaseIfNotJSCell(base, regT1);
- addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)));
+ addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset())));
Jump nonCell = jump();
linkSlowCase(iter); // base array check
- Jump notString = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr));
+ Jump notString = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info));
emitNakedCall(m_globalData->getCTIStub(stringGetByValStubGenerator).code());
Jump failed = branchTestPtr(Zero, regT0);
emitStore(dst, regT1, regT0);
addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
emitJumpSlowCaseIfNotJSCell(base, regT1);
- addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)));
+ addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset())));
emitWriteBarrier(regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess);
// regT0 holds a JSCell*
// Check for array
- Jump failureCases1 = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr));
+ Jump failureCases1 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info));
// Checks out okay! - get the length from the storage
loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
JSGlobalData* globalData = &callFrame->globalData();
- if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
+ if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress);
return;
}
- if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) {
+ if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
// The tradeoff of compiling an patched inline string length access routine does not seem
// to pay off, so we currently only do this for arrays.
ctiPatchCallByReturnAddress(codeBlock, returnAddress, globalData->jitStubs->ctiStringLengthTrampoline());
STUB_INIT_STACK_FRAME(stackFrame);
CallFrame* callFrame = stackFrame.callFrame;
- JSGlobalData* globalData = stackFrame.globalData;
JSValue baseValue = stackFrame.args[0].jsValue();
JSValue subscript = stackFrame.args[1].jsValue();
if (subscript.isUInt32()) {
uint32_t i = subscript.asUInt32();
- if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) {
+ if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string));
JSValue result = asString(baseValue)->getIndex(callFrame, i);
CHECK_FOR_EXCEPTION();
return JSValue::encode(result);
}
- if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+ if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
// All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array));
return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i));
STUB_INIT_STACK_FRAME(stackFrame);
CallFrame* callFrame = stackFrame.callFrame;
- JSGlobalData* globalData = stackFrame.globalData;
JSValue baseValue = stackFrame.args[0].jsValue();
JSValue subscript = stackFrame.args[1].jsValue();
if (LIKELY(subscript.isUInt32())) {
uint32_t i = subscript.asUInt32();
- if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i))
+ if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
result = asString(baseValue)->getIndex(callFrame, i);
else {
result = baseValue.get(callFrame, i);
- if (!isJSString(globalData, baseValue))
+ if (!isJSString(baseValue))
ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
}
} else {
STUB_INIT_STACK_FRAME(stackFrame);
CallFrame* callFrame = stackFrame.callFrame;
- JSGlobalData* globalData = stackFrame.globalData;
JSValue baseValue = stackFrame.args[0].jsValue();
JSValue subscript = stackFrame.args[1].jsValue();
if (LIKELY(subscript.isUInt32())) {
uint32_t i = subscript.asUInt32();
- if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+ if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
// All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i));
}
result = baseValue.get(callFrame, i);
- if (!isJSByteArray(globalData, baseValue))
+ if (!isJSByteArray(baseValue))
ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
} else {
Identifier property(callFrame, subscript.toString(callFrame));
if (LIKELY(subscript.isUInt32())) {
uint32_t i = subscript.asUInt32();
- if (isJSArray(globalData, baseValue)) {
+ if (isJSArray(baseValue)) {
JSArray* jsArray = asArray(baseValue);
if (jsArray->canSetIndex(i))
jsArray->setIndex(*globalData, i, value);
else
JSArray::putByIndex(jsArray, callFrame, i, value);
- } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+ } else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
JSByteArray* jsByteArray = asByteArray(baseValue);
ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_byte_array));
// All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
STUB_INIT_STACK_FRAME(stackFrame);
CallFrame* callFrame = stackFrame.callFrame;
- JSGlobalData* globalData = stackFrame.globalData;
JSValue baseValue = stackFrame.args[0].jsValue();
JSValue subscript = stackFrame.args[1].jsValue();
if (LIKELY(subscript.isUInt32())) {
uint32_t i = subscript.asUInt32();
- if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+ if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
JSByteArray* jsByteArray = asByteArray(baseValue);
// All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
}
}
- if (!isJSByteArray(globalData, baseValue))
+ if (!isJSByteArray(baseValue))
ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val));
baseValue.put(callFrame, i, value);
} else {
{
STUB_INIT_STACK_FRAME(stackFrame);
- return JSValue::encode(jsBoolean(isJSString(stackFrame.globalData, stackFrame.args[0].jsValue())));
+ return JSValue::encode(jsBoolean(isJSString(stackFrame.args[0].jsValue())));
}
DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_object)
void loadJSStringArgument(int argument, RegisterID dst)
{
loadCellArgument(argument, dst);
- m_failures.append(branchPtr(NotEqual, Address(dst, 0), TrustedImmPtr(m_globalData->jsStringVPtr)));
+ m_failures.append(branchPtr(NotEqual, Address(dst, JSCell::classInfoOffset()), TrustedImmPtr(&JSString::s_info)));
}
void loadInt32Argument(int argument, RegisterID dst, Jump& failTarget)
namespace JSC {
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(ArrayConstructor);
+
const ClassInfo ArrayConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::arrayConstructorTable, CREATE_METHOD_TABLE(ArrayConstructor) };
/* Source for ArrayConstructor.lut.h
{
JSValue thisValue = exec->hostThisValue();
- bool isRealArray = isJSArray(&exec->globalData(), thisValue);
+ bool isRealArray = isJSArray(thisValue);
if (!isRealArray && !thisValue.inherits(&JSArray::s_info))
return throwVMTypeError(exec);
JSArray* thisObj = asArray(thisValue);
separator = exec->argument(0).toString(exec);
unsigned k = 0;
- if (isJSArray(&exec->globalData(), thisObj)) {
+ if (isJSArray(thisObj)) {
JSArray* array = asArray(thisObj);
if (length) {
{
JSValue thisValue = exec->hostThisValue();
- if (isJSArray(&exec->globalData(), thisValue))
+ if (isJSArray(thisValue))
return JSValue::encode(asArray(thisValue)->pop());
JSObject* thisObj = thisValue.toObject(exec);
{
JSValue thisValue = exec->hostThisValue();
- if (isJSArray(&exec->globalData(), thisValue) && exec->argumentCount() == 1) {
+ if (isJSArray(thisValue) && exec->argumentCount() == 1) {
JSArray* array = asArray(thisValue);
array->push(exec, exec->argument(0));
return JSValue::encode(jsNumber(array->length()));
result = jsUndefined();
} else {
result = thisObj->get(exec, 0);
- if (isJSArray(&exec->globalData(), thisObj))
+ if (isJSArray(thisObj))
((JSArray *)thisObj)->shiftCount(exec, 1);
else {
for (unsigned k = 1; k < length; k++) {
unsigned additionalArgs = std::max<int>(exec->argumentCount() - 2, 0);
if (additionalArgs != deleteCount) {
if (additionalArgs < deleteCount) {
- if ((!begin) && (isJSArray(&exec->globalData(), thisObj)))
+ if ((!begin) && (isJSArray(thisObj)))
((JSArray *)thisObj)->shiftCount(exec, deleteCount - additionalArgs);
else {
for (unsigned k = begin; k < length - deleteCount; ++k) {
thisObj->methodTable()->deletePropertyByIndex(thisObj, exec, k - 1);
}
} else {
- if ((!begin) && (isJSArray(&exec->globalData(), thisObj)))
+ if ((!begin) && (isJSArray(thisObj)))
((JSArray *)thisObj)->unshiftCount(exec, additionalArgs - deleteCount);
else {
for (unsigned k = length - deleteCount; k > begin; --k) {
unsigned nrArgs = exec->argumentCount();
if ((nrArgs) && (length)) {
- if (isJSArray(&exec->globalData(), thisObj))
+ if (isJSArray(thisObj))
((JSArray *)thisObj)->unshiftCount(exec, nrArgs);
else {
for (unsigned k = length; k > 0; --k) {
unsigned filterIndex = 0;
unsigned k = 0;
- if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
+ if (callType == CallTypeJS && isJSArray(thisObj)) {
JSFunction* f = asFunction(function);
JSArray* array = asArray(thisObj);
CachedCall cachedCall(exec, f, 3);
JSArray* resultArray = constructEmptyArray(exec, length);
unsigned k = 0;
- if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
+ if (callType == CallTypeJS && isJSArray(thisObj)) {
JSFunction* f = asFunction(function);
JSArray* array = asArray(thisObj);
CachedCall cachedCall(exec, f, 3);
JSValue result = jsBoolean(true);
unsigned k = 0;
- if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
+ if (callType == CallTypeJS && isJSArray(thisObj)) {
JSFunction* f = asFunction(function);
JSArray* array = asArray(thisObj);
CachedCall cachedCall(exec, f, 3);
JSValue applyThis = exec->argument(1);
unsigned k = 0;
- if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
+ if (callType == CallTypeJS && isJSArray(thisObj)) {
JSFunction* f = asFunction(function);
JSArray* array = asArray(thisObj);
CachedCall cachedCall(exec, f, 3);
JSValue result = jsBoolean(false);
unsigned k = 0;
- if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
+ if (callType == CallTypeJS && isJSArray(thisObj)) {
JSFunction* f = asFunction(function);
JSArray* array = asArray(thisObj);
CachedCall cachedCall(exec, f, 3);
return throwVMTypeError(exec);
JSArray* array = 0;
- if (isJSArray(&exec->globalData(), thisObj))
+ if (isJSArray(thisObj))
array = asArray(thisObj);
if (exec->argumentCount() >= 2)
return throwVMTypeError(exec);
JSArray* array = 0;
- if (isJSArray(&exec->globalData(), thisObj))
+ if (isJSArray(thisObj))
array = asArray(thisObj);
if (exec->argumentCount() >= 2)
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(BooleanConstructor);
const ClassInfo BooleanConstructor::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(BooleanConstructor) };
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(BooleanObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(BooleanObject);
const ClassInfo BooleanObject::s_info = { "Boolean", &JSWrapperObject::s_info, 0, 0, CREATE_METHOD_TABLE(BooleanObject) };
*/
ASSERT_CLASS_FITS_IN_CELL(BooleanPrototype);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(BooleanPrototype);
BooleanPrototype::BooleanPrototype(ExecState* exec, Structure* structure)
: BooleanObject(exec->globalData(), structure)
struct HashTable;
struct MethodTable {
+ typedef void (*DestroyFunctionPtr)(JSCell*);
+ DestroyFunctionPtr destroy;
+
typedef void (*VisitChildrenFunctionPtr)(JSCell*, SlotVisitor&);
VisitChildrenFunctionPtr visitChildren;
#define HAS_MEMBER_NAMED(klass, name) (MemberCheck##name<klass>::has)
#define CREATE_METHOD_TABLE(ClassName) { \
+ &ClassName::destroy, \
&ClassName::visitChildren, \
&ClassName::getCallData, \
&ClassName::getConstructData, \
*/
ASSERT_CLASS_FITS_IN_CELL(DateConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(DateConstructor);
DateConstructor::DateConstructor(JSGlobalObject* globalObject, Structure* structure)
: InternalFunction(globalObject, structure)
setInternalValue(globalData, jsNumber(timeClip(time)));
}
+void DateInstance::destroy(JSCell* cell)
+{
+ jsCast<DateInstance*>(cell)->DateInstance::~DateInstance();
+}
+
const GregorianDateTime* DateInstance::calculateGregorianDateTime(ExecState* exec) const
{
double milli = internalNumber();
DateInstance(ExecState*, Structure*);
void finishCreation(JSGlobalData&);
void finishCreation(JSGlobalData&, double);
-
+
+ static void destroy(JSCell*);
+
public:
typedef JSWrapperObject Base;
const ClassInfo StrictModeTypeErrorFunction::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(StrictModeTypeErrorFunction) };
+void StrictModeTypeErrorFunction::destroy(JSCell* cell)
+{
+ jsCast<StrictModeTypeErrorFunction*>(cell)->StrictModeTypeErrorFunction::~StrictModeTypeErrorFunction();
+}
+
JSValue createTypeErrorFunction(ExecState* exec, const UString& message)
{
JSGlobalObject* globalObject = exec->lexicalGlobalObject();
{
}
+ static void destroy(JSCell*);
+
public:
typedef InternalFunction Base;
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(ErrorConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(ErrorConstructor);
const ClassInfo ErrorConstructor::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(ErrorConstructor) };
namespace JSC {
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(ErrorInstance);
+
const ClassInfo ErrorInstance::s_info = { "Error", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(ErrorInstance) };
ErrorInstance::ErrorInstance(JSGlobalData& globalData, Structure* structure)
namespace JSC {
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(InterruptedExecutionError);
+
const ClassInfo InterruptedExecutionError::s_info = { "InterruptedExecutionError", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(InterruptedExecutionError) };
JSValue InterruptedExecutionError::defaultValue(const JSObject*, ExecState* exec, PreferredPrimitiveType hint)
}
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(TerminatedExecutionError);
+
const ClassInfo TerminatedExecutionError::s_info = { "TerminatedExecutionError", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(TerminatedExecutionError) };
JSValue TerminatedExecutionError::defaultValue(const JSObject*, ExecState* exec, PreferredPrimitiveType hint)
const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0, CREATE_METHOD_TABLE(ExecutableBase) };
+void ExecutableBase::destroy(JSCell* cell)
+{
+ jsCast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
+}
+
inline void ExecutableBase::clearCode()
{
#if ENABLE(JIT)
const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(NativeExecutable) };
-NativeExecutable::~NativeExecutable()
+void NativeExecutable::destroy(JSCell* cell)
{
+ jsCast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
}
#if ENABLE(DFG_JIT)
const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
+void ScriptExecutable::destroy(JSCell* cell)
+{
+ jsCast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
+}
+
const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(EvalExecutable) };
EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
{
}
-EvalExecutable::~EvalExecutable()
+void EvalExecutable::destroy(JSCell* cell)
{
+ jsCast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();
}
const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(ProgramExecutable) };
{
}
-ProgramExecutable::~ProgramExecutable()
+void ProgramExecutable::destroy(JSCell* cell)
{
+ jsCast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();
}
const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionExecutable) };
{
}
-FunctionExecutable::~FunctionExecutable()
+void FunctionExecutable::destroy(JSCell* cell)
{
+ jsCast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
}
JSObject* EvalExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
public:
typedef JSCell Base;
+ static void destroy(JSCell*);
+
bool isHostFunction() const
{
ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
}
#endif
- virtual ~NativeExecutable();
+ static void destroy(JSCell*);
NativeFunction function() { return m_function; }
NativeFunction constructor() { return m_constructor; }
{
}
+ static void destroy(JSCell*);
+
const SourceCode& source() { return m_source; }
intptr_t sourceID() const { return m_source.provider()->asID(); }
const UString& sourceURL() const { return m_source.provider()->url(); }
public:
typedef ScriptExecutable Base;
- virtual ~EvalExecutable();
+ static void destroy(JSCell*);
JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
{
return executable;
}
- virtual ~ProgramExecutable();
+ static void destroy(JSCell*);
JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
{
return executable;
}
- virtual ~FunctionExecutable();
+ static void destroy(JSCell*);
JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain)
{
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(FunctionConstructor);
const ClassInfo FunctionConstructor::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionConstructor) };
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(FunctionPrototype);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(FunctionPrototype);
const ClassInfo FunctionPrototype::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(FunctionPrototype) };
if (asArguments(array)->length(exec) > Arguments::MaxArguments)
return JSValue::encode(throwStackOverflowError(exec));
asArguments(array)->fillArgList(exec, applyArgs);
- } else if (isJSArray(&exec->globalData(), array)) {
+ } else if (isJSArray(array)) {
if (asArray(array)->length() > Arguments::MaxArguments)
return JSValue::encode(throwStackOverflowError(exec));
asArray(array)->fillArgList(exec, applyArgs);
namespace JSC {
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(GetterSetter);
+
const ClassInfo GetterSetter::s_info = { "GetterSetter", 0, 0, 0, CREATE_METHOD_TABLE(GetterSetter) };
void GetterSetter::visitChildren(JSCell* cell, SlotVisitor& visitor)
#if ENABLE(WRITE_BARRIER_PROFILING)
WriteBarrierCounters::initialize();
#endif
- JSGlobalData::storeVPtrs();
#if ENABLE(JIT) && ENABLE(ASSEMBLER)
ExecutableAllocator::initializeAllocator();
#endif
namespace JSC {
-// Ensure the compiler generates a vtable for InternalFunction!
-void InternalFunction::vtableAnchor() {}
-
ASSERT_CLASS_FITS_IN_CELL(InternalFunction);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(InternalFunction);
const ClassInfo InternalFunction::s_info = { "Function", &JSNonFinalObject::s_info, 0, 0, CREATE_METHOD_TABLE(InternalFunction) };
-InternalFunction::InternalFunction(VPtrStealingHackType)
- : JSNonFinalObject(VPtrStealingHack)
-{
-}
-
InternalFunction::InternalFunction(JSGlobalObject* globalObject, Structure* structure)
: JSNonFinalObject(globalObject->globalData(), structure)
{
{
JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName);
- if (displayName && isJSString(&exec->globalData(), displayName))
+ if (displayName && isJSString(displayName))
return asString(displayName)->tryGetValue();
return UString();
protected:
static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags;
- // Only used to allow us to determine the JSFunction vptr
- InternalFunction(VPtrStealingHackType);
-
InternalFunction(JSGlobalObject*, Structure*);
void finishCreation(JSGlobalData&, const Identifier& name);
static CallType getCallData(JSCell*, CallData&);
-
- private:
- virtual void vtableAnchor();
};
InternalFunction* asInternalFunction(JSValue);
namespace JSC {
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSAPIValueWrapper);
+
const ClassInfo JSAPIValueWrapper::s_info = { "API Wrapper", 0, 0, 0, CREATE_METHOD_TABLE(JSAPIValueWrapper) };
} // namespace JSC
#endif
-JSArray::JSArray(VPtrStealingHackType)
- : JSNonFinalObject(VPtrStealingHack)
-{
-}
-
JSArray::JSArray(JSGlobalData& globalData, Structure* structure)
: JSNonFinalObject(globalData, structure)
{
JSArray::~JSArray()
{
- ASSERT(vptr() == JSGlobalData::jsArrayVPtr);
+ ASSERT(jsCast<JSArray*>(this));
checkConsistency(DestructorConsistencyCheck);
delete m_storage->m_sparseValueMap;
fastFree(m_storage->m_allocBase);
}
+void JSArray::destroy(JSCell* cell)
+{
+ jsCast<JSArray*>(cell)->JSArray::~JSArray();
+}
+
bool JSArray::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned i, PropertySlot& slot)
{
JSArray* thisObject = jsCast<JSArray*>(cell);
public:
typedef JSNonFinalObject Base;
- JSArray(VPtrStealingHackType);
- virtual ~JSArray();
+ ~JSArray();
+ static void destroy(JSCell*);
static JSArray* create(JSGlobalData& globalData, Structure* structure)
{
return asArray(value.asCell());
}
- inline bool isJSArray(JSGlobalData* globalData, JSCell* cell) { return cell->vptr() == globalData->jsArrayVPtr; }
- inline bool isJSArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && isJSArray(globalData, v.asCell()); }
+ inline bool isJSArray(JSCell* cell) { return cell->classInfo() == &JSArray::s_info; }
+ inline bool isJSArray(JSValue v) { return v.isCell() && isJSArray(v.asCell()); }
// Rule from ECMA 15.2 about what an array index is.
// Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSBoundFunction);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSBoundFunction);
const ClassInfo JSBoundFunction::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSBoundFunction) };
{
JSBoundFunction* boundFunction = static_cast<JSBoundFunction*>(exec->callee());
- ASSERT(isJSArray(&exec->globalData(), boundFunction->boundArgs())); // Currently this is true!
+ ASSERT(isJSArray(boundFunction->boundArgs())); // Currently this is true!
JSArray* boundArgs = asArray(boundFunction->boundArgs());
MarkedArgumentBuffer args;
{
JSBoundFunction* boundFunction = static_cast<JSBoundFunction*>(exec->callee());
- ASSERT(isJSArray(&exec->globalData(), boundFunction->boundArgs())); // Currently this is true!
+ ASSERT(isJSArray(boundFunction->boundArgs())); // Currently this is true!
JSArray* boundArgs = asArray(boundFunction->boundArgs());
MarkedArgumentBuffer args;
{
}
-#if !ASSERT_DISABLED
JSByteArray::~JSByteArray()
{
- ASSERT(vptr() == JSGlobalData::jsByteArrayVPtr);
+ ASSERT(jsCast<JSByteArray*>(this));
}
-#endif
+void JSByteArray::destroy(JSCell* cell)
+{
+ jsCast<JSByteArray*>(cell)->JSByteArray::~JSByteArray();
+}
Structure* JSByteArray::createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype, const JSC::ClassInfo* classInfo)
{
WTF::ByteArray* storage() const { return m_storage.get(); }
-#if !ASSERT_DISABLED
- virtual ~JSByteArray();
-#endif
+ ~JSByteArray();
+ static void destroy(JSCell*);
static size_t offsetOfStorage() { return OBJECT_OFFSETOF(JSByteArray, m_storage); }
}
private:
- JSByteArray(VPtrStealingHackType)
- : JSNonFinalObject(VPtrStealingHack)
- {
- }
-
RefPtr<WTF::ByteArray> m_storage;
};
return static_cast<JSByteArray*>(value.asCell());
}
- inline bool isJSByteArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsByteArrayVPtr; }
+ inline bool isJSByteArray(JSValue v) { return v.isCell() && v.asCell()->classInfo() == &JSByteArray::s_info; }
} // namespace JSC
namespace JSC {
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSCell);
+
+void JSCell::destroy(JSCell* cell)
+{
+ cell->JSCell::~JSCell();
+}
+
bool JSCell::getString(ExecState* exec, UString&stringValue) const
{
if (!isString())
enum CreatingEarlyCellTag { CreatingEarlyCell };
JSCell(CreatingEarlyCellTag);
- enum VPtrStealingHackType { VPtrStealingHack };
- explicit JSCell(VPtrStealingHackType) { }
-
public:
void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; } // Used for initialization after GC allocation.
protected:
JSCell(JSGlobalData&, Structure*);
- virtual ~JSCell(); // Invoked by GC finalization.
+ static void destroy(JSCell*);
public:
// Querying the type.
// Object operations, with the toObject operation included.
const ClassInfo* classInfo() const;
+ const ClassInfo* validatedClassInfo() const;
const MethodTable* methodTable() const;
static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue);
static JSObject* toThisObject(JSCell*, ExecState*);
- void* vptr() const { ASSERT(!isZapped()); return *reinterpret_cast<void* const*>(this); }
- void setVPtr(void* vptr) { *reinterpret_cast<void**>(this) = vptr; ASSERT(!isZapped()); }
void zap() { *reinterpret_cast<uintptr_t**>(this) = 0; }
bool isZapped() const { return !*reinterpret_cast<uintptr_t* const*>(this); }
{
return OBJECT_OFFSETOF(JSCell, m_structure);
}
+
+ static ptrdiff_t classInfoOffset()
+ {
+ return OBJECT_OFFSETOF(JSCell, m_classInfo);
+ }
void* structureAddress()
{
static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
private:
+ const ClassInfo* m_classInfo;
WriteBarrier<Structure> m_structure;
};
-
- inline JSCell::JSCell(JSGlobalData& globalData, Structure* structure)
- : m_structure(globalData, this, structure)
- {
- }
inline JSCell::JSCell(CreatingEarlyCellTag)
{
ASSERT(m_structure);
}
- inline void JSCell::finishCreation(JSGlobalData& globalData, Structure* structure, CreatingEarlyCellTag)
- {
-#if ENABLE(GC_VALIDATION)
- ASSERT(globalData.isInitializingObject());
- globalData.setInitializingObject(false);
- if (structure)
-#endif
- m_structure.setEarlyValue(globalData, this, structure);
- // Very first set of allocations won't have a real structure.
- ASSERT(m_structure || !globalData.structureStructure);
- }
-
- inline JSCell::~JSCell()
+ inline Structure* JSCell::structure() const
{
+ return m_structure.get();
}
- inline Structure* JSCell::structure() const
+ inline const ClassInfo* JSCell::classInfo() const
{
- return m_structure.get();
+ return m_classInfo;
}
inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
return function;
}
-JSFunction::JSFunction(VPtrStealingHackType)
- : Base(VPtrStealingHack)
-{
-}
-
JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
: Base(exec->globalData(), structure)
, m_executable()
putDirectOffset(exec->globalData(), scopeChainNode->globalObject->functionNameOffset(), executable->nameValue());
}
-JSFunction::~JSFunction()
+void JSFunction::destroy(JSCell* cell)
{
- ASSERT(vptr() == JSGlobalData::jsFunctionVPtr);
-}
-
-void JSFunction::vtableAnchor()
-{
- fprintf(stderr, "We need something here that Visual Studio can't optimize away.\n");
+ JSFunction* thisObject = jsCast<JSFunction*>(cell);
+ ASSERT(thisObject->classInfo()->isSubClassOf(&JSFunction::s_info));
+ thisObject->JSFunction::~JSFunction();
}
void createDescriptorForThrowingProperty(ExecState* exec, PropertyDescriptor& descriptor, const char* message)
{
JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName);
- if (displayName && isJSString(&exec->globalData(), displayName))
+ if (displayName && isJSString(displayName))
return asString(displayName)->tryGetValue();
return UString();
class JSGlobalObject;
class NativeExecutable;
class SourceCode;
- class VPtrHackExecutable;
namespace DFG {
class SpeculativeJIT;
class JITCompiler;
return function;
}
- virtual ~JSFunction();
- virtual void vtableAnchor(); // FIXME: Remove this once optimizations no longer rely on testing vtables
+ static void destroy(JSCell*);
const UString& name(ExecState*);
const UString displayName(ExecState*);
static void visitChildren(JSCell*, SlotVisitor&);
private:
- explicit JSFunction(VPtrStealingHackType);
-
bool isHostFunctionNonInline() const;
static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
extern const HashTable stringTable;
extern const HashTable stringConstructorTable;
-void* JSGlobalData::jsFinalObjectVPtr;
-void* JSGlobalData::jsArrayVPtr;
-void* JSGlobalData::jsByteArrayVPtr;
-void* JSGlobalData::jsStringVPtr;
-void* JSGlobalData::jsFunctionVPtr;
-
#if COMPILER(GCC)
// Work around for gcc trying to coalesce our reads of the various cell vptrs
#define CLOBBER_MEMORY() do { \
#define CLOBBER_MEMORY() do { } while (false)
#endif
-void JSGlobalData::storeVPtrs()
-{
- // Enough storage to fit a JSArray, JSByteArray, JSString, or JSFunction.
- // COMPILE_ASSERTS below check that this is true.
- char storage[64];
-
- COMPILE_ASSERT(sizeof(JSFinalObject) <= sizeof(storage), sizeof_JSFinalObject_must_be_less_than_storage);
- JSCell* jsFinalObject = new (storage) JSFinalObject(JSFinalObject::VPtrStealingHack);
- CLOBBER_MEMORY();
- JSGlobalData::jsFinalObjectVPtr = jsFinalObject->vptr();
-
- COMPILE_ASSERT(sizeof(JSArray) <= sizeof(storage), sizeof_JSArray_must_be_less_than_storage);
- JSCell* jsArray = new (storage) JSArray(JSArray::VPtrStealingHack);
- CLOBBER_MEMORY();
- JSGlobalData::jsArrayVPtr = jsArray->vptr();
-
- COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(storage), sizeof_JSByteArray_must_be_less_than_storage);
- JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
- CLOBBER_MEMORY();
- JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
-
- COMPILE_ASSERT(sizeof(JSString) <= sizeof(storage), sizeof_JSString_must_be_less_than_storage);
- JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
- CLOBBER_MEMORY();
- JSGlobalData::jsStringVPtr = jsString->vptr();
-
- COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(storage), sizeof_JSFunction_must_be_less_than_storage);
- JSCell* jsFunction = new (storage) JSFunction(JSCell::VPtrStealingHack);
- CLOBBER_MEMORY();
- JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
-
- // Until we fully remove our reliance on vptrs, we need to make sure that everybody that
- // we think has a unique virtual pointer actually does.
- if (jsFinalObjectVPtr == jsArrayVPtr
- || jsFinalObjectVPtr == jsByteArrayVPtr
- || jsFinalObjectVPtr == jsStringVPtr
- || jsFinalObjectVPtr == jsFunctionVPtr
- || jsArrayVPtr == jsByteArrayVPtr
- || jsArrayVPtr == jsStringVPtr
- || jsArrayVPtr == jsFunctionVPtr
- || jsByteArrayVPtr == jsStringVPtr
- || jsByteArrayVPtr == jsFunctionVPtr
- || jsStringVPtr == jsFunctionVPtr)
- CRASH();
-}
-
JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType, HeapSize heapSize)
: globalDataType(globalDataType)
, clientData(0)
struct TypedArrayDescriptor {
TypedArrayDescriptor()
- : m_vptr(0)
+ : m_classInfo(0)
, m_storageOffset(0)
, m_lengthOffset(0)
{
}
- TypedArrayDescriptor(void* vptr, size_t storageOffset, size_t lengthOffset)
- : m_vptr(vptr)
+ TypedArrayDescriptor(const ClassInfo* classInfo, size_t storageOffset, size_t lengthOffset)
+ : m_classInfo(classInfo)
, m_storageOffset(storageOffset)
, m_lengthOffset(lengthOffset)
{
}
- void* m_vptr;
+ const ClassInfo* m_classInfo;
size_t m_storageOffset;
size_t m_lengthOffset;
};
Strong<Structure> regExpStructure;
Strong<Structure> structureChainStructure;
- static void storeVPtrs();
- static JS_EXPORTDATA void* jsFinalObjectVPtr;
- static JS_EXPORTDATA void* jsArrayVPtr;
- static JS_EXPORTDATA void* jsByteArrayVPtr;
- static JS_EXPORTDATA void* jsStringVPtr;
- static JS_EXPORTDATA void* jsFunctionVPtr;
-
IdentifierTable* identifierTable;
CommonIdentifiers* propertyNames;
const MarkedArgumentBuffer* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark.
#define registerTypedArrayFunction(type, capitalizedType) \
void registerTypedArrayDescriptor(const capitalizedType##Array*, const TypedArrayDescriptor& descriptor) \
{ \
- ASSERT(!m_##type##ArrayDescriptor.m_vptr || m_##type##ArrayDescriptor.m_vptr == descriptor.m_vptr); \
+ ASSERT(!m_##type##ArrayDescriptor.m_classInfo || m_##type##ArrayDescriptor.m_classInfo == descriptor.m_classInfo); \
m_##type##ArrayDescriptor = descriptor; \
} \
const TypedArrayDescriptor& type##ArrayDescriptor() const { return m_##type##ArrayDescriptor; }
}
}
+void JSGlobalObject::destroy(JSCell* cell)
+{
+ jsCast<JSGlobalObject*>(cell)->JSGlobalObject::~JSGlobalObject();
+}
+
void JSGlobalObject::init(JSObject* thisValue)
{
ASSERT(JSLock::currentThreadIsHoldingLock());
}
public:
- virtual ~JSGlobalObject();
+ ~JSGlobalObject();
+ static void destroy(JSCell*);
static void visitChildren(JSCell*, SlotVisitor&);
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSGlobalThis);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSGlobalThis);
const ClassInfo JSGlobalThis::s_info = { "JSGlobalThis", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSGlobalThis) };
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSNotAnObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSNotAnObject);
const ClassInfo JSNotAnObject::s_info = { "Object", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSNotAnObject) };
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSONObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSONObject);
static EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState*);
static EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState*);
// First time through, initialize.
if (!m_index) {
if (m_isArray) {
- m_isJSArray = isJSArray(&exec->globalData(), m_object.get());
+ m_isJSArray = isJSArray(m_object.get());
m_size = m_object->get(exec, exec->globalData().propertyNames->length).toUInt32(exec);
builder.append('[');
} else {
arrayStartState:
case ArrayStartState: {
ASSERT(inValue.isObject());
- ASSERT(isJSArray(&m_exec->globalData(), asObject(inValue)) || asObject(inValue)->inherits(&JSArray::s_info));
+ ASSERT(isJSArray(asObject(inValue)) || asObject(inValue)->inherits(&JSArray::s_info));
if (objectStack.size() + arrayStack.size() > maximumFilterRecursion)
return throwError(m_exec, createStackOverflowError(m_exec));
indexStack.removeLast();
break;
}
- if (isJSArray(&m_exec->globalData(), array) && array->canGetIndex(index))
+ if (isJSArray(array) && array->canGetIndex(index))
inValue = array->getIndex(index);
else {
PropertySlot slot;
if (filteredValue.isUndefined())
array->methodTable()->deletePropertyByIndex(array, m_exec, indexStack.last());
else {
- if (isJSArray(&m_exec->globalData(), array) && array->canSetIndex(indexStack.last()))
+ if (isJSArray(array) && array->canSetIndex(indexStack.last()))
array->setIndex(m_exec->globalData(), indexStack.last(), filteredValue);
else
array->methodTable()->putByIndex(array, m_exec, indexStack.last(), filteredValue);
objectStartState:
case ObjectStartState: {
ASSERT(inValue.isObject());
- ASSERT(!isJSArray(&m_exec->globalData(), asObject(inValue)) && !asObject(inValue)->inherits(&JSArray::s_info));
+ ASSERT(!isJSArray(asObject(inValue)) && !asObject(inValue)->inherits(&JSArray::s_info));
if (objectStack.size() + arrayStack.size() > maximumFilterRecursion)
return throwError(m_exec, createStackOverflowError(m_exec));
break;
}
JSObject* object = asObject(inValue);
- if (isJSArray(&m_exec->globalData(), object) || object->inherits(&JSArray::s_info))
+ if (isJSArray(object) || object->inherits(&JSArray::s_info))
goto arrayStartState;
goto objectStartState;
}
ASSERT_CLASS_FITS_IN_CELL(JSNonFinalObject);
ASSERT_CLASS_FITS_IN_CELL(JSFinalObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSObject);
+
const char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property.";
const ClassInfo JSObject::s_info = { "Object", 0, 0, 0, CREATE_METHOD_TABLE(JSObject) };
const ClassInfo JSFinalObject::s_info = { "Object", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSFinalObject) };
-void JSFinalObject::vtableAnchor()
+void JSFinalObject::destroy(JSCell* cell)
+{
+ jsCast<JSFinalObject*>(cell)->JSFinalObject::~JSFinalObject();
+}
+
+void JSNonFinalObject::destroy(JSCell* cell)
{
- printf("Something Visual Studio can't optimize away.\n");
+ jsCast<JSNonFinalObject*>(cell)->JSNonFinalObject::~JSNonFinalObject();
}
static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode)
delete [] jsCast<JSObject*>(cell)->m_propertyStorage.get();
}
-void JSObject::vtableAnchor()
+void JSObject::destroy(JSCell* cell)
{
+ jsCast<JSObject*>(cell)->JSObject::~JSObject();
}
void JSObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
public:
typedef JSCell Base;
- virtual void vtableAnchor();
+ static void destroy(JSCell*);
static void visitChildren(JSCell*, SlotVisitor&);
ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
ASSERT_UNUSED(inlineStorage, static_cast<void*>(inlineStorage) == static_cast<void*>(this + 1));
ASSERT(structure()->isObject());
+ ASSERT(classInfo());
}
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
// To instantiate objects you likely want JSFinalObject, below.
// To create derived types you likely want JSNonFinalObject, below.
JSObject(JSGlobalData&, Structure*, PropertyStorage inlineStorage);
- JSObject(VPtrStealingHackType, PropertyStorage inlineStorage)
- : JSCell(VPtrStealingHack)
- , m_propertyStorage(inlineStorage, StorageBarrier::Unchecked)
- {
- }
private:
// Nobody should ever ask any of these questions on something already known to be a JSObject.
return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
}
+ static void destroy(JSCell*);
+
protected:
- explicit JSNonFinalObject(VPtrStealingHackType)
- : JSObject(VPtrStealingHack, m_inlineStorage)
- {
- }
-
explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure)
: JSObject(globalData, structure, m_inlineStorage)
{
Base::finishCreation(globalData, m_inlineStorage);
ASSERT(!(OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage) % sizeof(double)));
ASSERT(this->structure()->propertyStorageCapacity() == JSNonFinalObject_inlineStorageCapacity);
+ ASSERT(classInfo());
}
private:
public:
typedef JSObject Base;
- explicit JSFinalObject(VPtrStealingHackType)
- : JSObject(VPtrStealingHack, m_inlineStorage)
- {
- }
-
static JSFinalObject* create(ExecState* exec, Structure* structure)
{
JSFinalObject* finalObject = new (allocateCell<JSFinalObject>(*exec->heap())) JSFinalObject(exec->globalData(), structure);
Base::finishCreation(globalData, m_inlineStorage);
ASSERT(!(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) % sizeof(double)));
ASSERT(this->structure()->propertyStorageCapacity() == JSFinalObject_inlineStorageCapacity);
+ ASSERT(classInfo());
}
+ static void destroy(JSCell*);
+
private:
explicit JSFinalObject(JSGlobalData& globalData, Structure* structure)
: JSObject(globalData, structure, m_inlineStorage)
{
}
- virtual void vtableAnchor();
-
static const unsigned StructureFlags = JSObject::StructureFlags;
WriteBarrierBase<Unknown> m_inlineStorage[JSFinalObject_inlineStorageCapacity];
};
+inline bool isJSFinalObject(JSCell* cell)
+{
+ return cell->classInfo() == &JSFinalObject::s_info;
+}
+
+inline bool isJSFinalObject(JSValue value)
+{
+ return value.isCell() && isJSFinalObject(value.asCell());
+}
+
inline size_t JSObject::offsetOfInlineStorage()
{
ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) == OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage));
return jsPropertyNameIterator;
}
+void JSPropertyNameIterator::destroy(JSCell* cell)
+{
+ jsCast<JSPropertyNameIterator*>(cell)->JSPropertyNameIterator::~JSPropertyNameIterator();
+}
+
JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
{
JSValue identifier = m_jsStrings[i].get();
iterator->finishCreation(exec, propertyNameArrayData);
return iterator;
}
-
+
+ static void destroy(JSCell*);
+
static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
{
return Structure::create(globalData, globalObject, prototype, TypeInfo(CompoundType, OverridesVisitChildren), &s_info);
const ClassInfo JSStaticScopeObject::s_info = { "Object", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSStaticScopeObject) };
+void JSStaticScopeObject::destroy(JSCell* cell)
+{
+ jsCast<JSStaticScopeObject*>(cell)->JSStaticScopeObject::~JSStaticScopeObject();
+}
+
void JSStaticScopeObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
JSStaticScopeObject* thisObject = jsCast<JSStaticScopeObject*>(cell);
: JSVariableObject(exec->globalData(), exec->globalData().staticScopeStructure.get(), &m_symbolTable, reinterpret_cast<Register*>(&m_registerStore + 1))
{
}
-
+
+ static void destroy(JSCell*);
+
SymbolTable m_symbolTable;
WriteBarrier<Unknown> m_registerStore;
};
append(jsString);
}
-JSString::~JSString()
+void JSString::destroy(JSCell* cell)
{
- ASSERT(vptr() == JSGlobalData::jsStringVPtr);
+ JSString* thisObject = jsCast<JSString*>(cell);
+ thisObject->JSString::~JSString();
}
void JSString::visitChildren(JSCell* cell, SlotVisitor& visitor)
typedef JSCell Base;
+ static void destroy(JSCell*);
+
class RopeBuilder {
public:
RopeBuilder(JSGlobalData& globalData)
return newString;
}
- virtual ~JSString();
-
const UString& value(ExecState* exec) const
{
if (isRope())
static void visitChildren(JSCell*, SlotVisitor&);
private:
- JSString(VPtrStealingHackType)
- : JSCell(VPtrStealingHack)
- {
- }
-
void resolveRope(ExecState*) const;
void resolveRopeSlowCase8(LChar*) const;
void resolveRopeSlowCase(UChar*) const;
JSString* asString(JSValue);
- // When an object is created from a different DLL, MSVC changes vptr to a "local" one right after invoking a constructor,
- // see <http://groups.google.com/group/microsoft.public.vc.language/msg/55cdcefeaf770212>.
- // This breaks isJSString(), and we don't need that hack anyway, so we change vptr back to primary one.
- // The below function must be called by any inline function that invokes a JSString constructor.
-#if COMPILER(MSVC) && !defined(BUILDING_JavaScriptCore)
- inline JSString* fixupVPtr(JSGlobalData* globalData, JSString* string) { string->setVPtr(globalData->jsStringVPtr); return string; }
-#else
- inline JSString* fixupVPtr(JSGlobalData*, JSString* string) { return string; }
-#endif
-
inline JSString* asString(JSValue value)
{
ASSERT(value.asCell()->isString());
{
if (c <= maxSingleCharacterString)
return globalData->smallStrings.singleCharacterString(globalData, c);
- return fixupVPtr(globalData, JSString::create(*globalData, UString(&c, 1).impl()));
+ return JSString::create(*globalData, UString(&c, 1).impl());
}
inline JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset)
UChar c = s[offset];
if (c <= maxSingleCharacterString)
return globalData->smallStrings.singleCharacterString(globalData, c);
- return fixupVPtr(globalData, JSString::create(*globalData, StringImpl::create(s.impl(), offset, 1)));
+ return JSString::create(*globalData, StringImpl::create(s.impl(), offset, 1));
}
inline JSString* jsNontrivialString(JSGlobalData* globalData, const char* s)
ASSERT(s);
ASSERT(s[0]);
ASSERT(s[1]);
- return fixupVPtr(globalData, JSString::create(*globalData, UString(s).impl()));
+ return JSString::create(*globalData, UString(s).impl());
}
inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s)
{
ASSERT(s.length() > 1);
- return fixupVPtr(globalData, JSString::create(*globalData, s.impl()));
+ return JSString::create(*globalData, s.impl());
}
inline JSString* JSString::getIndex(ExecState* exec, unsigned i)
if (c <= maxSingleCharacterString)
return globalData->smallStrings.singleCharacterString(globalData, c);
}
- return fixupVPtr(globalData, JSString::create(*globalData, s.impl()));
+ return JSString::create(*globalData, s.impl());
}
inline JSString* jsSubstring(ExecState* exec, JSString* s, unsigned offset, unsigned length)
if (c <= maxSingleCharacterString)
return globalData->smallStrings.singleCharacterString(globalData, c);
}
- return fixupVPtr(globalData, JSString::createHasOtherOwner(*globalData, StringImpl::create8(s.impl(), offset, length)));
+ return JSString::createHasOtherOwner(*globalData, StringImpl::create8(s.impl(), offset, length));
}
inline JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
if (c <= maxSingleCharacterString)
return globalData->smallStrings.singleCharacterString(globalData, c);
}
- return fixupVPtr(globalData, JSString::createHasOtherOwner(*globalData, StringImpl::create(s.impl(), offset, length)));
+ return JSString::createHasOtherOwner(*globalData, StringImpl::create(s.impl(), offset, length));
}
inline JSString* jsOwnedString(JSGlobalData* globalData, const UString& s)
if (c <= maxSingleCharacterString)
return globalData->smallStrings.singleCharacterString(globalData, c);
}
- return fixupVPtr(globalData, JSString::createHasOtherOwner(*globalData, s.impl()));
+ return JSString::createHasOtherOwner(*globalData, s.impl());
}
inline JSString* jsStringBuilder(JSGlobalData* globalData)
{
- return fixupVPtr(globalData, JSString::createNull(*globalData));
+ return JSString::createNull(*globalData);
}
inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); }
return false;
}
- inline bool isJSString(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsStringVPtr; }
+ inline bool isJSString(JSValue v) { return v.isCell() && v.asCell()->classInfo() == &JSString::s_info; }
inline bool JSCell::toBoolean(ExecState* exec) const
{
namespace JSC {
-JSVariableObject::~JSVariableObject()
+void JSVariableObject::destroy(JSCell* cell)
{
+ jsCast<JSVariableObject*>(cell)->JSVariableObject::~JSVariableObject();
}
bool JSVariableObject::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
SymbolTable& symbolTable() const { return *m_symbolTable; }
- virtual ~JSVariableObject();
+ static void destroy(JSCell*);
static NO_RETURN_DUE_TO_ASSERT void putWithAttributes(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes);
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject);
-
-JSWrapperObject::~JSWrapperObject()
-{
-}
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSWrapperObject);
void JSWrapperObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
static void visitChildren(JSCell*, SlotVisitor&);
- virtual ~JSWrapperObject();
-
private:
WriteBarrier<Unknown> m_internalValue;
};
namespace JSC {
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(MathObject);
+
const ClassInfo MathObject::s_info = { "Math", &JSNonFinalObject::s_info, 0, ExecState::mathTable, CREATE_METHOD_TABLE(MathObject) };
/* Source for MathObject.lut.h
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(NativeErrorConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(NativeErrorConstructor);
const ClassInfo NativeErrorConstructor::s_info = { "Function", &InternalFunction::s_info, 0, 0, CREATE_METHOD_TABLE(NativeErrorConstructor) };
namespace JSC {
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(NumberConstructor);
+
const ClassInfo NumberConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::numberConstructorTable, CREATE_METHOD_TABLE(NumberConstructor) };
/* Source for NumberConstructor.lut.h
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(NumberObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(NumberObject);
const ClassInfo NumberObject::s_info = { "Number", &JSWrapperObject::s_info, 0, 0, CREATE_METHOD_TABLE(NumberObject) };
*/
ASSERT_CLASS_FITS_IN_CELL(NumberPrototype);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(NumberPrototype);
NumberPrototype::NumberPrototype(ExecState* exec, Structure* structure)
: NumberObject(exec->globalData(), structure)
namespace JSC {
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(ObjectConstructor);
+
const ClassInfo ObjectConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::objectConstructorTable, CREATE_METHOD_TABLE(ObjectConstructor) };
/* Source for ObjectConstructor.lut.h
namespace JSC {
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(ObjectPrototype);
+
const ClassInfo ObjectPrototype::s_info = { "Object", &JSNonFinalObject::s_info, 0, ExecState::objectPrototypeTable, CREATE_METHOD_TABLE(ObjectPrototype) };
/* Source for ObjectPrototype.lut.h
if ((length1 + length2) < length1)
return throwOutOfMemoryError(exec);
- return fixupVPtr(&globalData, JSString::create(globalData, s1, s2));
+ return JSString::create(globalData, s1, s2);
}
ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, const UString& u2, const UString& u3)
if ((length1 + length2 + length3) < length3)
return throwOutOfMemoryError(exec);
- return fixupVPtr(globalData, JSString::create(exec->globalData(), jsString(globalData, u1), jsString(globalData, u2), jsString(globalData, u3)));
+ return JSString::create(exec->globalData(), jsString(globalData, u1), jsString(globalData, u2), jsString(globalData, u3));
}
ALWAYS_INLINE JSValue jsString(ExecState* exec, Register* strings, unsigned count)
if (v1.isNumber() && v2.isNumber())
return v1.asNumber() < v2.asNumber();
- JSGlobalData* globalData = &callFrame->globalData();
- if (isJSString(globalData, v1) && isJSString(globalData, v2))
+ if (isJSString(v1) && isJSString(v2))
return asString(v1)->value(callFrame) < asString(v2)->value(callFrame);
double n1;
if (v1.isNumber() && v2.isNumber())
return v1.asNumber() <= v2.asNumber();
- JSGlobalData* globalData = &callFrame->globalData();
- if (isJSString(globalData, v1) && isJSString(globalData, v2))
+ if (isJSString(v1) && isJSString(v2))
return !(asString(v2)->value(callFrame) < asString(v1)->value(callFrame));
double n1;
m_numSubpatterns = pattern.m_numSubpatterns;
}
-RegExp::~RegExp()
+void RegExp::destroy(JSCell* cell)
{
+ RegExp* thisObject = jsCast<RegExp*>(cell);
#if REGEXP_FUNC_TEST_DATA_GEN
RegExpFunctionalTestCollector::get()->clearRegExp(this);
#endif
+ thisObject->RegExp::~RegExp();
}
RegExp* RegExp::createWithoutCaching(JSGlobalData& globalData, const UString& patternString, RegExpFlags flags)
typedef JSCell Base;
static RegExp* create(JSGlobalData&, const UString& pattern, RegExpFlags);
- ~RegExp();
+ static void destroy(JSCell*);
bool global() const { return m_flags & FlagGlobal; }
bool ignoreCase() const { return m_flags & FlagIgnoreCase; }
putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(2), ReadOnly | DontDelete | DontEnum);
}
+void RegExpConstructor::destroy(JSCell* cell)
+{
+ jsCast<RegExpConstructor*>(cell)->RegExpConstructor::~RegExpConstructor();
+}
+
RegExpMatchesArray::RegExpMatchesArray(ExecState* exec)
: JSArray(exec->globalData(), exec->lexicalGlobalObject()->regExpMatchesArrayStructure())
{
delete static_cast<RegExpConstructorPrivate*>(subclassData());
}
+void RegExpMatchesArray::destroy(JSCell* cell)
+{
+ jsCast<RegExpMatchesArray*>(cell)->RegExpMatchesArray::~RegExpMatchesArray();
+}
+
void RegExpMatchesArray::fillArrayInstance(ExecState* exec)
{
RegExpConstructorPrivate* d = static_cast<RegExpConstructorPrivate*>(subclassData());
private:
RegExpConstructor(JSGlobalObject*, Structure*);
+ static void destroy(JSCell*);
static ConstructType getConstructData(JSCell*, ConstructData&);
static CallType getCallData(JSCell*, CallData&);
regExp->finishCreation(exec->globalData(), ctorPrivate);
return regExp;
}
- virtual ~RegExpMatchesArray();
+ ~RegExpMatchesArray();
+ static void destroy(JSCell*);
static JS_EXPORTDATA const ClassInfo s_info;
ASSERT(inherits(&s_info));
}
-RegExpObject::~RegExpObject()
+void RegExpObject::destroy(JSCell* cell)
{
+ jsCast<RegExpObject*>(cell)->RegExpObject::~RegExpObject();
}
void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
return object;
}
- virtual ~RegExpObject();
-
void setRegExp(JSGlobalData& globalData, RegExp* r) { d->regExp.set(globalData, this, r); }
RegExp* regExp() const { return d->regExp.get(); }
protected:
RegExpObject(JSGlobalObject*, Structure*, RegExp*);
void finishCreation(JSGlobalObject*);
+ static void destroy(JSCell*);
+
static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | Base::StructureFlags;
static void visitChildren(JSCell*, SlotVisitor&);
namespace JSC {
-ScopeChainNode::~ScopeChainNode()
-{
-}
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(ScopeChainNode);
#ifndef NDEBUG
{
}
- virtual ~ScopeChainNode();
-
protected:
void finishCreation(JSGlobalData* globalData, JSGlobalObject* globalObject)
{
namespace JSC {
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(StrictEvalActivation);
+
const ClassInfo StrictEvalActivation::s_info = { "Object", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(StrictEvalActivation) };
StrictEvalActivation::StrictEvalActivation(ExecState* exec)
*/
ASSERT_CLASS_FITS_IN_CELL(StringConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(StringConstructor);
StringConstructor::StringConstructor(JSGlobalObject* globalObject, Structure* structure)
: InternalFunction(globalObject, structure)
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(StringObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(StringObject);
const ClassInfo StringObject::s_info = { "String", &JSWrapperObject::s_info, 0, 0, CREATE_METHOD_TABLE(StringObject) };
{
}
-void StringObject::vtableAnchor()
-{
-}
-
void StringObject::finishCreation(JSGlobalData& globalData, JSString* string)
{
Base::finishCreation(globalData);
public:
typedef JSWrapperObject Base;
- virtual void vtableAnchor();
-
static StringObject* create(ExecState* exec, Structure* structure)
{
JSString* string = jsEmptyString(exec);
namespace JSC {
ASSERT_CLASS_FITS_IN_CELL(StringPrototype);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(StringPrototype);
static EncodedJSValue JSC_HOST_CALL stringProtoFuncToString(ExecState*);
static EncodedJSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState*);
m_globalObject.set(globalData, this, previous->m_globalObject.get());
}
-Structure::~Structure()
+void Structure::destroy(JSCell* cell)
{
+ jsCast<Structure*>(cell)->Structure::~Structure();
}
void Structure::materializePropertyMap(JSGlobalData& globalData)
Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*);
- ~Structure();
+ static void destroy(JSCell*);
// These should be used with caution.
size_t addPropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
inline void JSCell::setStructure(JSGlobalData& globalData, Structure* structure)
{
ASSERT(structure->typeInfo().overridesVisitChildren() == this->structure()->typeInfo().overridesVisitChildren());
+ ASSERT(structure->classInfo() == m_structure->classInfo());
m_structure.set(globalData, this, structure);
}
- inline const ClassInfo* JSCell::classInfo() const
+ inline const ClassInfo* JSCell::validatedClassInfo() const
{
#if ENABLE(GC_VALIDATION)
- return m_structure.unvalidatedGet()->classInfo();
+ ASSERT(m_structure.unvalidatedGet()->classInfo() == m_classInfo);
#else
- return m_structure->classInfo();
+ ASSERT(m_structure->classInfo() == m_classInfo);
#endif
+ return m_classInfo;
}
ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell)
return false;
}
+ inline JSCell::JSCell(JSGlobalData& globalData, Structure* structure)
+ : m_classInfo(structure->classInfo())
+ , m_structure(globalData, this, structure)
+ {
+ }
+
+ inline void JSCell::finishCreation(JSGlobalData& globalData, Structure* structure, CreatingEarlyCellTag)
+ {
+#if ENABLE(GC_VALIDATION)
+ ASSERT(globalData.isInitializingObject());
+ globalData.setInitializingObject(false);
+ if (structure)
+#endif
+ m_structure.setEarlyValue(globalData, this, structure);
+ m_classInfo = structure->classInfo();
+ // Very first set of allocations won't have a real structure.
+ ASSERT(m_structure || !globalData.structureStructure);
+ }
+
} // namespace JSC
#endif // Structure_h
{
}
-StructureChain::~StructureChain()
+void StructureChain::destroy(JSCell* cell)
{
+ jsCast<StructureChain*>(cell)->StructureChain::~StructureChain();
}
void StructureChain::visitChildren(JSCell* cell, SlotVisitor& visitor)
private:
StructureChain(JSGlobalData&, Structure*);
- ~StructureChain();
+ static void destroy(JSCell*);
OwnArrayPtr<WriteBarrier<Structure> > m_vector;
};
#define ASSERT_GC_OBJECT_INHERITS(object, classInfo) do { (void)object; (void)classInfo; } while (0)
#endif
+#if COMPILER(CLANG)
+#define ASSERT_HAS_TRIVIAL_DESTRUCTOR(klass) COMPILE_ASSERT(__has_trivial_destructor(klass), klass##_has_trivial_destructor_check)
+#else
+#define ASSERT_HAS_TRIVIAL_DESTRUCTOR(klass)
+#endif
+
#endif /* WTF_Assertions_h */
+2011-12-16 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ De-virtualize destructors
+ https://bugs.webkit.org/show_bug.cgi?id=74331
+
+ Reviewed by Geoffrey Garen.
+
+ * UserObjectImp.cpp: Add static destroy function.
+ (UserObjectImp::destroy):
+ * UserObjectImp.h:
+
2011-12-14 Hajime Morrita <morrita@chromium.org>
JS_INLINE and WTF_INLINE should be visible from WebCore
fJSUserObject->Release();
}
+void UserObjectImp::destroy(JSCell* cell)
+{
+ jsCast<UserObjectImp*>(cell)->UserObjectImp::~UserObjectImp();
+}
+
CallType UserObjectImp::getCallData(JSCell* cell, CallData& callData)
{
UserObjectImp* thisObject = jsCast<UserObjectImp*>(cell);
return object;
}
- virtual ~UserObjectImp();
+ ~UserObjectImp();
+ static void destroy(JSCell*);
static const ClassInfo s_info;
static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
- virtual JSValue callAsFunction(ExecState *exec);
+ JSValue callAsFunction(ExecState*); // TODO: Figure out how to re-virtualize this without breaking the fact that we don't allow vptrs in the JSCell hierarchy.
static bool getOwnPropertySlot(JSCell*, ExecState *, const Identifier&, PropertySlot&);
static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
JSValue toPrimitive(ExecState*, PreferredPrimitiveType preferredType = NoPreference) const;
- virtual bool toBoolean(ExecState *exec) const;
+ bool toBoolean(ExecState*) const; // TODO: Figure out how to re-virtualize this without breaking the fact that we don't allow vptrs in the JSCell hierarchy.
static void visitChildren(JSCell*, SlotVisitor&);
+2011-12-16 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ De-virtualize destructors
+ https://bugs.webkit.org/show_bug.cgi?id=74331
+
+ Reviewed by Geoffrey Garen.
+
+ No new tests.
+
+ Doing everything here that was done to the JSCell hierarchy in JavaScriptCore.
+ See the ChangeLog for this commit for a more in-depth description.
+
+ * WebCore.exp.in: Add/remove symbols.
+ * bindings/js/JSCanvasRenderingContext2DCustom.cpp: Remove first arg from isJSArray call.
+ (WebCore::JSCanvasRenderingContext2D::setWebkitLineDash):
+ * bindings/js/JSDOMBinding.cpp: Add trival destructor assert for DOMConstructorObject
+ and DOMConstructorWithDocument.
+ * bindings/js/JSDOMGlobalObject.cpp: Add static destroy. Add implementation for
+ scriptExecutionContext that dispatches to different functions in subclasses
+ depending on our current ClassInfo. We do this so that we can get rid of the
+ virtual-ness of scriptExecutionContext, because any virtual functions will throw
+ off the layout of the object and we'll crash at runtime.
+ (WebCore::JSDOMGlobalObject::destroy):
+ (WebCore::JSDOMGlobalObject::scriptExecutionContext):
+ * bindings/js/JSDOMGlobalObject.h:
+ * bindings/js/JSDOMWindowBase.cpp: Add static destroy.
+ (WebCore::JSDOMWindowBase::destroy):
+ * bindings/js/JSDOMWindowBase.h: De-virtualize scriptExecutionContext.
+ * bindings/js/JSDOMWindowShell.cpp: Add static destroy.
+ (WebCore::JSDOMWindowShell::destroy):
+ * bindings/js/JSDOMWindowShell.h:
+ * bindings/js/JSDOMWrapper.cpp: Add trivial destructor assert.
+ * bindings/js/JSDOMWrapper.h: Add a ClassInfo to JSDOMWrapper since it now overrides
+ a MethodTable function. Remove vtableAnchor virtual function.
+ * bindings/js/JSImageConstructor.cpp: Add trivial destructor assert.
+ * bindings/js/JSNodeCustom.cpp: Change implementation of pushEventHandlerScope so that
+ it dispatches to the correct function depending on the
+ identity of the class as specified by the ClassInfo.
+ See JSDOMGlobalObject::scriptExecutionContext for explanation.
+ (WebCore::JSNode::pushEventHandlerScope):
+ * bindings/js/JSWebSocketCustom.cpp: Remove first arg to isJSArray call.
+ (WebCore::JSWebSocketConstructor::constructJSWebSocket):
+ * bindings/js/JSWorkerContextBase.cpp: Add static destroy.
+ (WebCore::JSWorkerContextBase::destroy):
+ * bindings/js/JSWorkerContextBase.h:
+ * bindings/js/ScriptValue.cpp: Remove first arg to isJSArray call.
+ (WebCore::jsToInspectorValue):
+ * bindings/js/SerializedScriptValue.cpp: Ditto.
+ (WebCore::CloneSerializer::isArray):
+ (WebCore::CloneSerializer::getSparseIndex):
+ * bindings/scripts/CodeGeneratorJS.pm:
+ (GenerateHeader): Remove virtual-ness of any custom pushEventHandlerScope (see
+ JSNodeCustom::pushEventHandlerScope for explanation). Remove virtual toBoolean
+ for anybody who masquerades as undefined, since our JSObject implementation handles
+ this based on the TypeInfo in the Structure. Add trivial destructor assert for any
+ class other than DOMWindow or WorkerContexts.
+ (GenerateImplementation): Change ClassInfo definitions to use Base::s_info, since
+ typing the parent class more than once is duplication of information and increases
+ the likelihood of mistakes. Pass ClassInfo to TypeArrayDescriptors instead of vptr.
+ (GenerateConstructorDefinition): Add trivial destructor assert for all generated constructors.
+ * bridge/c/CRuntimeObject.cpp: Remove empty virtual destructor.
+ * bridge/c/CRuntimeObject.h:
+ * bridge/jni/jsc/JavaRuntimeObject.cpp: Ditto.
+ * bridge/jni/jsc/JavaRuntimeObject.h:
+ * bridge/objc/ObjCRuntimeObject.h: Ditto.
+ * bridge/objc/ObjCRuntimeObject.mm:
+ * bridge/objc/objc_runtime.h: Add static destroy for ObjcFallbackObjectImp. De-virtualize
+ toBoolean in the short term. Need longer term fix.
+ * bridge/objc/objc_runtime.mm:
+ (JSC::Bindings::ObjcFallbackObjectImp::destroy):
+ * bridge/qt/qt_runtime.cpp: Add static destroy to QtRuntimeMethod.
+ (JSC::Bindings::QtRuntimeMethod::destroy):
+ * bridge/qt/qt_runtime.h: De-virtualize ~QtRuntimeMethod.
+ * bridge/runtime_array.cpp: De-virtualize destructor. Add static destroy.
+ (JSC::RuntimeArray::destroy):
+ * bridge/runtime_array.h:
+ * bridge/runtime_method.cpp: Remove vtableAnchor. Add static destroy.
+ (JSC::RuntimeMethod::destroy):
+ * bridge/runtime_method.h:
+ * bridge/runtime_object.cpp: Add static destroy.
+ (JSC::Bindings::RuntimeObject::destroy):
+ * bridge/runtime_object.h:
+
2011-12-15 Alexey Proskuryakov <ap@apple.com>
Poor XPath performance when evaluating an expression that returns a lot of nodes
__ZN7WebCore12IconDatabase5closeEv
__ZN7WebCore12IconDatabase9setClientEPNS_18IconDatabaseClientE
__ZN7WebCore12IconDatabaseC1Ev
-__ZN7WebCore12JSDOMWrapper34virtualFunctionToPreventWeakVtableEv
+__ZN7WebCore12JSDOMWrapper6s_infoE
__ZN7WebCore12PopupMenuMacC1EPNS_15PopupMenuClientE
__ZN7WebCore12PrintContext12pagePropertyEPNS_5FrameEPKci
__ZN7WebCore12PrintContext13numberOfPagesEPNS_5FrameERKNS_9FloatSizeE
__ZNK7WebCore16VisibleSelection19rootEditableElementEv
__ZNK7WebCore16VisibleSelection23isContentRichlyEditableEv
__ZNK7WebCore16VisibleSelection5isAllENS_27EditingBoundaryCrossingRuleE
+__ZNK7WebCore17JSDOMGlobalObject22scriptExecutionContextEv
__ZNK7WebCore17RegularExpression13matchedLengthEv
__ZNK7WebCore17RegularExpression5matchERKN3WTF6StringEiPi
__ZNK7WebCore17RegularExpression9searchRevERKN3WTF6StringE
__ZNK7WebCore9PageCache21autoreleasedPageCountEv
__ZNK7WebCore9TreeScope14getElementByIdERKN3WTF12AtomicStringE
__ZTVN7WebCore12ChromeClientE
-__ZTVN7WebCore12JSDOMWrapperE
__ZTVN7WebCore16IconDatabaseBaseE
__ZTVN7WebCore17FrameLoaderClientE
__ZTVN7WebCore18PlatformStrategiesE
#if USE(PLUGIN_HOST_PROCESS)
__ZN3JSC13RuntimeMethod11getCallDataEPNS_6JSCellERNS_8CallDataE
-__ZN3JSC13RuntimeMethod12vtableAnchorEv
__ZN3JSC13RuntimeMethod14finishCreationERNS_12JSGlobalDataERKNS_10IdentifierE
__ZN3JSC13RuntimeMethod18getOwnPropertySlotEPNS_6JSCellEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
__ZN3JSC13RuntimeMethod24getOwnPropertyDescriptorEPNS_8JSObjectEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
__ZN3JSC13RuntimeMethod6s_infoE
+__ZN3JSC13RuntimeMethod7destroyEPNS_6JSCellE
__ZN3JSC13RuntimeMethodC2EPNS_14JSGlobalObjectEPNS_9StructureERN3WTF6VectorIPNS_8Bindings6MethodELm0EEE
__ZN3JSC8Bindings10RootObjectD1Ev
__ZN3JSC8Bindings13RuntimeObject11getCallDataEPNS_6JSCellERNS_8CallDataE
__ZN3JSC8Bindings13RuntimeObject24getOwnPropertyDescriptorEPNS_8JSObjectEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
__ZN3JSC8Bindings13RuntimeObject3putEPNS_6JSCellEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
__ZN3JSC8Bindings13RuntimeObject6s_infoE
+__ZN3JSC8Bindings13RuntimeObject7destroyEPNS_6JSCellE
__ZN3JSC8Bindings13RuntimeObjectC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEN3WTF10PassRefPtrINS0_8InstanceEEE
-__ZN3JSC8Bindings13RuntimeObjectD2Ev
__ZN3JSC8Bindings8Instance19createRuntimeObjectEPNS_9ExecStateE
__ZN3JSC8Bindings8InstanceC2EN3WTF10PassRefPtrINS0_10RootObjectEEE
__ZN3JSC8Bindings8InstanceD2Ev
__ZN7WebCore13IdentifierRep7isValidEPS0_
__ZN7WebCore16ScriptController16createRootObjectEPv
-__ZTVN3JSC13RuntimeMethodE
#endif
#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
void JSCanvasRenderingContext2D::setWebkitLineDash(ExecState* exec, JSValue value)
{
- if (!isJSArray(&exec->globalData(), value))
+ if (!isJSArray(value))
return;
DashArray dash;
namespace WebCore {
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(DOMConstructorObject);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(DOMConstructorWithDocument);
+
const JSC::HashTable* getHashTableForGlobalData(JSGlobalData& globalData, const JSC::HashTable* staticTable)
{
return DOMObjectHashTableMap::mapFor(globalData).get(staticTable);
{
}
-JSDOMGlobalObject::~JSDOMGlobalObject()
+void JSDOMGlobalObject::destroy(JSCell* cell)
{
+ jsCast<JSDOMGlobalObject*>(cell)->JSDOMGlobalObject::~JSDOMGlobalObject();
}
void JSDOMGlobalObject::finishCreation(JSGlobalData& globalData)
ASSERT(inherits(&s_info));
}
+ScriptExecutionContext* JSDOMGlobalObject::scriptExecutionContext() const
+{
+ if (inherits(&JSDOMWindowBase::s_info))
+ return jsCast<const JSDOMWindowBase*>(this)->scriptExecutionContext();
+#if ENABLE(WORKERS)
+ if (inherits(&JSWorkerContextBase::s_info))
+ return jsCast<const JSWorkerContextBase*>(this)->scriptExecutionContext();
+#endif
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
void JSDOMGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
JSDOMGlobalObject* thisObject = jsCast<JSDOMGlobalObject*>(cell);
struct JSDOMGlobalObjectData;
JSDOMGlobalObject(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<DOMWrapperWorld>, const JSC::GlobalObjectMethodTable* = 0);
- virtual ~JSDOMGlobalObject();
+ static void destroy(JSC::JSCell*);
void finishCreation(JSC::JSGlobalData&);
void finishCreation(JSC::JSGlobalData&, JSC::JSGlobalThis*);
JSDOMStructureMap& structures() { return m_structures; }
JSDOMConstructorMap& constructors() { return m_constructors; }
- virtual ScriptExecutionContext* scriptExecutionContext() const = 0;
+ ScriptExecutionContext* scriptExecutionContext() const;
// Make binding code generation easier.
JSDOMGlobalObject* globalObject() { return this; }
addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
}
+void JSDOMWindowBase::destroy(JSCell* cell)
+{
+ jsCast<JSDOMWindowBase*>(cell)->JSDOMWindowBase::~JSDOMWindowBase();
+}
+
void JSDOMWindowBase::updateDocument()
{
ASSERT(m_impl->document());
JSDOMWindowBase(JSC::JSGlobalData&, JSC::Structure*, PassRefPtr<DOMWindow>, JSDOMWindowShell*);
void finishCreation(JSC::JSGlobalData&, JSDOMWindowShell*);
+ static void destroy(JSCell*);
+
public:
void updateDocument();
DOMWindow* impl() const { return m_impl.get(); }
- virtual ScriptExecutionContext* scriptExecutionContext() const;
+ ScriptExecutionContext* scriptExecutionContext() const;
// Called just before removing this window from the JSDOMWindowShell.
void willRemoveFromWindowShell();
setWindow(window);
}
-JSDOMWindowShell::~JSDOMWindowShell()
+void JSDOMWindowShell::destroy(JSCell* cell)
{
+ jsCast<JSDOMWindowShell*>(cell)->JSDOMWindowShell::~JSDOMWindowShell();
}
void JSDOMWindowShell::setWindow(PassRefPtr<DOMWindow> domWindow)
typedef JSC::JSGlobalThis Base;
public:
JSDOMWindowShell(PassRefPtr<DOMWindow>, JSC::Structure*, DOMWrapperWorld*);
- virtual ~JSDOMWindowShell();
+ static void destroy(JSCell*);
JSDOMWindow* window() const { return static_cast<JSDOMWindow*>(m_unwrappedObject.get()); }
void setWindow(JSC::JSGlobalData& globalData, JSDOMWindow* window)
namespace WebCore {
-void JSDOMWrapper::virtualFunctionToPreventWeakVtable()
-{
- ASSERT_NOT_REACHED();
-}
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSDOMWrapper);
+
+const ClassInfo JSDOMWrapper::s_info = { "JSDOMWrapper", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSDOMWrapper) };
} // namespace WebCore
return globalObject()->scriptExecutionContext();
}
+ static const JSC::ClassInfo s_info;
+
static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
{
return JSC::Structure::create(globalData, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), &s_info);
}
protected:
- // An inline function cannot be the first non-abstract virtual function declared
- // in the class as it results in the vtable being generated as a weak symbol.
- virtual void virtualFunctionToPreventWeakVtable();
-
explicit JSDOMWrapper(JSC::Structure* structure, JSC::JSGlobalObject* globalObject)
: JSNonFinalObject(globalObject->globalData(), structure)
{
namespace WebCore {
ASSERT_CLASS_FITS_IN_CELL(JSImageConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSImageConstructor);
-const ClassInfo JSImageConstructor::s_info = { "ImageConstructor", &DOMConstructorWithDocument::s_info, 0, 0, CREATE_METHOD_TABLE(JSImageConstructor) };
+const ClassInfo JSImageConstructor::s_info = { "ImageConstructor", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSImageConstructor) };
JSImageConstructor::JSImageConstructor(Structure* structure, JSDOMGlobalObject* globalObject)
: DOMConstructorWithDocument(structure, globalObject)
return jsNull();
}
-ScopeChainNode* JSNode::pushEventHandlerScope(ExecState*, ScopeChainNode* node) const
+ScopeChainNode* JSNode::pushEventHandlerScope(ExecState* exec, ScopeChainNode* node) const
{
+ if (inherits(&JSHTMLElement::s_info))
+ return jsCast<const JSHTMLElement*>(this)->pushEventHandlerScope(exec, node);
return node;
}
webSocket->connect(urlString, ec);
else {
JSValue protocolsValue = exec->argument(1);
- if (isJSArray(&exec->globalData(), protocolsValue)) {
+ if (isJSArray(protocolsValue)) {
Vector<String> protocols;
JSArray* protocolsArray = asArray(protocolsValue);
for (unsigned i = 0; i < protocolsArray->length(); ++i) {
ASSERT(inherits(&s_info));
}
-JSWorkerContextBase::~JSWorkerContextBase()
+void JSWorkerContextBase::destroy(JSCell* cell)
{
+ jsCast<JSWorkerContextBase*>(cell)->JSWorkerContextBase::~JSWorkerContextBase();
}
ScriptExecutionContext* JSWorkerContextBase::scriptExecutionContext() const
class JSWorkerContextBase : public JSDOMGlobalObject {
typedef JSDOMGlobalObject Base;
public:
- virtual ~JSWorkerContextBase();
+ static void destroy(JSC::JSCell*);
static const JSC::ClassInfo s_info;
WorkerContext* impl() const { return m_impl.get(); }
- virtual ScriptExecutionContext* scriptExecutionContext() const;
+ ScriptExecutionContext* scriptExecutionContext() const;
static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
{
return InspectorString::create(String(s.characters(), s.length()));
}
if (value.isObject()) {
- if (isJSArray(&scriptState->globalData(), value)) {
+ if (isJSArray(value)) {
RefPtr<InspectorArray> inspectorArray = InspectorArray::create();
JSArray* array = asArray(value);
unsigned length = array->length();
if (!value.isObject())
return false;
JSObject* object = asObject(value);
- return isJSArray(&m_exec->globalData(), object) || object->inherits(&JSArray::s_info);
+ return isJSArray(object) || object->inherits(&JSArray::s_info);
}
bool startObjectInternal(JSObject* object)
JSValue getSparseIndex(JSArray* array, unsigned propertyName, bool& hasIndex)
{
PropertySlot slot(array);
- if (isJSArray(&m_exec->globalData(), array)) {
+ if (isJSArray(array)) {
if (JSArray::getOwnPropertySlotByIndex(array, m_exec, propertyName, slot)) {
hasIndex = true;
return slot.getValue(m_exec, propertyName);
push(@headerContent, " }\n\n");
# Custom pushEventHandlerScope function
- push(@headerContent, " virtual JSC::ScopeChainNode* pushEventHandlerScope(JSC::ExecState*, JSC::ScopeChainNode*) const;\n\n") if $dataNode->extendedAttributes->{"CustomPushEventHandlerScope"};
+ push(@headerContent, " JSC::ScopeChainNode* pushEventHandlerScope(JSC::ExecState*, JSC::ScopeChainNode*) const;\n\n") if $dataNode->extendedAttributes->{"CustomPushEventHandlerScope"};
# Custom call functions
push(@headerContent, " static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData&);\n\n") if $dataNode->extendedAttributes->{"CustomCall"};
# Override toBoolean to return false for objects that want to 'MasqueradesAsUndefined'.
if ($dataNode->extendedAttributes->{"MasqueradesAsUndefined"}) {
- push(@headerContent, " virtual bool toBoolean(JSC::ExecState*) const { return false; };\n");
$structureFlags{"JSC::MasqueradesAsUndefined"} = 1;
}
push(@implContent, "\nusing namespace JSC;\n\n");
push(@implContent, "namespace WebCore {\n\n");
- push(@implContent, "ASSERT_CLASS_FITS_IN_CELL($className);\n\n");
+ push(@implContent, "ASSERT_CLASS_FITS_IN_CELL($className);\n");
+ if ($interfaceName ne "DOMWindow" && !$dataNode->extendedAttributes->{"IsWorkerContext"}) {
+ push(@implContent, "ASSERT_HAS_TRIVIAL_DESTRUCTOR($className);\n\n");
+ }
my $numAttributes = GenerateAttributesHashTable($object, $dataNode);
push(@implContent, "{\n");
push(@implContent, " return getHashTableForGlobalData(exec->globalData(), &${className}PrototypeTable);\n");
push(@implContent, "}\n\n");
- push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", &JSC::JSNonFinalObject::s_info, 0, get${className}PrototypeTable, CREATE_METHOD_TABLE(${className}Prototype) };\n\n");
+ push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", &Base::s_info, 0, get${className}PrototypeTable, CREATE_METHOD_TABLE(${className}Prototype) };\n\n");
} else {
- push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", &JSC::JSNonFinalObject::s_info, &${className}PrototypeTable, 0, CREATE_METHOD_TABLE(${className}Prototype) };\n\n");
+ push(@implContent, "const ClassInfo ${className}Prototype::s_info = { \"${visibleClassName}Prototype\", &Base::s_info, &${className}PrototypeTable, 0, CREATE_METHOD_TABLE(${className}Prototype) };\n\n");
}
if ($interfaceName ne "DOMWindow" && !$dataNode->extendedAttributes->{"IsWorkerContext"}) {
push(@implContent, "JSObject* ${className}Prototype::self(ExecState* exec, JSGlobalObject* globalObject)\n");
push(@implContent, " return getDOMPrototype<${className}>(exec, globalObject);\n");
push(@implContent, "}\n\n");
}
+
if ($numConstants > 0 || $numFunctions > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
push(@implContent, "bool ${className}Prototype::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
push(@implContent, "{\n");
push(@implContent, "}\n\n");
}
- push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleClassName}\", &" . $parentClassName . "::s_info, ");
+ push(@implContent, "const ClassInfo $className" . "::s_info = { \"${visibleClassName}\", &Base::s_info, ");
if ($numAttributes > 0 && !$dataNode->extendedAttributes->{"NoStaticTables"}) {
push(@implContent, "&${className}Table");
push(@implContent, "{\n");
push(@implContent, " Base::finishCreation(globalData);\n");
if (IsTypedArrayType($implType) and ($implType ne "ArrayBufferView") and ($implType ne "ArrayBuffer")) {
- push(@implContent, " TypedArrayDescriptor descriptor(vptr(), OBJECT_OFFSETOF(${className}, m_storage), OBJECT_OFFSETOF(${className}, m_storageLength));\n");
+ push(@implContent, " TypedArrayDescriptor descriptor(&${className}::s_info, OBJECT_OFFSETOF(${className}, m_storage), OBJECT_OFFSETOF(${className}, m_storageLength));\n");
push(@implContent, " globalData.registerTypedArrayDescriptor(impl(), descriptor);\n");
push(@implContent, " m_storage = impl()->data();\n");
push(@implContent, " m_storageLength = impl()->length();\n");
my $numberOfconstructParameters = $dataNode->extendedAttributes->{"ConstructorParameters"};
if ($generatingNamedConstructor) {
- push(@$outputArray, "const ClassInfo ${constructorClassName}::s_info = { \"${visibleClassName}Constructor\", &DOMConstructorObject::s_info, 0, 0, CREATE_METHOD_TABLE($constructorClassName) };\n\n");
+ push(@$outputArray, "const ClassInfo ${constructorClassName}::s_info = { \"${visibleClassName}Constructor\", &Base::s_info, 0, 0, CREATE_METHOD_TABLE($constructorClassName) };\n\n");
push(@$outputArray, "${constructorClassName}::${constructorClassName}(Structure* structure, JSDOMGlobalObject* globalObject)\n");
push(@$outputArray, " : DOMConstructorWithDocument(structure, globalObject)\n");
push(@$outputArray, "{\n");
push(@$outputArray, "}\n\n");
} else {
- push(@$outputArray, "const ClassInfo ${constructorClassName}::s_info = { \"${visibleClassName}Constructor\", &DOMConstructorObject::s_info, &${constructorClassName}Table, 0, CREATE_METHOD_TABLE($constructorClassName) };\n\n");
+ push(@$outputArray, "ASSERT_HAS_TRIVIAL_DESTRUCTOR(${constructorClassName});\n\n");
+
+ push(@$outputArray, "const ClassInfo ${constructorClassName}::s_info = { \"${visibleClassName}Constructor\", &Base::s_info, &${constructorClassName}Table, 0, CREATE_METHOD_TABLE($constructorClassName) };\n\n");
push(@$outputArray, "${constructorClassName}::${constructorClassName}(Structure* structure, JSDOMGlobalObject* globalObject)\n");
push(@$outputArray, " : DOMConstructorObject(structure, globalObject)\n");
push(@$outputArray, "{\n");
namespace WebCore {
ASSERT_CLASS_FITS_IN_CELL(JSFloat64Array);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSFloat64Array);
/* Hash table */
};
static const HashTable JSFloat64ArrayConstructorTable = { 1, 0, JSFloat64ArrayConstructorTableValues, 0 };
-const ClassInfo JSFloat64ArrayConstructor::s_info = { "Float64ArrayConstructor", &DOMConstructorObject::s_info, &JSFloat64ArrayConstructorTable, 0, CREATE_METHOD_TABLE(JSFloat64ArrayConstructor) };
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSFloat64ArrayConstructor);
+
+const ClassInfo JSFloat64ArrayConstructor::s_info = { "Float64ArrayConstructor", &Base::s_info, &JSFloat64ArrayConstructorTable, 0, CREATE_METHOD_TABLE(JSFloat64ArrayConstructor) };
JSFloat64ArrayConstructor::JSFloat64ArrayConstructor(Structure* structure, JSDOMGlobalObject* globalObject)
: DOMConstructorObject(structure, globalObject)
return getHashTableForGlobalData(exec->globalData(), &JSFloat64ArrayPrototypeTable);
}
-const ClassInfo JSFloat64ArrayPrototype::s_info = { "Float64ArrayPrototype", &JSC::JSNonFinalObject::s_info, 0, getJSFloat64ArrayPrototypeTable, CREATE_METHOD_TABLE(JSFloat64ArrayPrototype) };
+const ClassInfo JSFloat64ArrayPrototype::s_info = { "Float64ArrayPrototype", &Base::s_info, 0, getJSFloat64ArrayPrototypeTable, CREATE_METHOD_TABLE(JSFloat64ArrayPrototype) };
JSObject* JSFloat64ArrayPrototype::self(ExecState* exec, JSGlobalObject* globalObject)
{
return getHashTableForGlobalData(exec->globalData(), &JSFloat64ArrayTable);
}
-const ClassInfo JSFloat64Array::s_info = { "Float64Array", &JSArrayBufferView::s_info, 0, getJSFloat64ArrayTable , CREATE_METHOD_TABLE(JSFloat64Array) };
+const ClassInfo JSFloat64Array::s_info = { "Float64Array", &Base::s_info, 0, getJSFloat64ArrayTable , CREATE_METHOD_TABLE(JSFloat64Array) };
JSFloat64Array::JSFloat64Array(Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<Float64Array> impl)
: JSArrayBufferView(structure, globalObject, impl)
void JSFloat64Array::finishCreation(JSGlobalData& globalData)
{
Base::finishCreation(globalData);
- TypedArrayDescriptor descriptor(vptr(), OBJECT_OFFSETOF(JSFloat64Array, m_storage), OBJECT_OFFSETOF(JSFloat64Array, m_storageLength));
+ TypedArrayDescriptor descriptor(&JSFloat64Array::s_info, OBJECT_OFFSETOF(JSFloat64Array, m_storage), OBJECT_OFFSETOF(JSFloat64Array, m_storageLength));
globalData.registerTypedArrayDescriptor(impl(), descriptor);
m_storage = impl()->data();
m_storageLength = impl()->length();
namespace WebCore {
ASSERT_CLASS_FITS_IN_CELL(JSTestEventConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSTestEventConstructor);
/* Hash table for constructor */
};
static const HashTable JSTestEventConstructorConstructorTable = { 1, 0, JSTestEventConstructorConstructorTableValues, 0 };
-const ClassInfo JSTestEventConstructorConstructor::s_info = { "TestEventConstructorConstructor", &DOMConstructorObject::s_info, &JSTestEventConstructorConstructorTable, 0, CREATE_METHOD_TABLE(JSTestEventConstructorConstructor) };
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSTestEventConstructorConstructor);
+
+const ClassInfo JSTestEventConstructorConstructor::s_info = { "TestEventConstructorConstructor", &Base::s_info, &JSTestEventConstructorConstructorTable, 0, CREATE_METHOD_TABLE(JSTestEventConstructorConstructor) };
JSTestEventConstructorConstructor::JSTestEventConstructorConstructor(Structure* structure, JSDOMGlobalObject* globalObject)
: DOMConstructorObject(structure, globalObject)
};
static const HashTable JSTestEventConstructorPrototypeTable = { 1, 0, JSTestEventConstructorPrototypeTableValues, 0 };
-const ClassInfo JSTestEventConstructorPrototype::s_info = { "TestEventConstructorPrototype", &JSC::JSNonFinalObject::s_info, &JSTestEventConstructorPrototypeTable, 0, CREATE_METHOD_TABLE(JSTestEventConstructorPrototype) };
+const ClassInfo JSTestEventConstructorPrototype::s_info = { "TestEventConstructorPrototype", &Base::s_info, &JSTestEventConstructorPrototypeTable, 0, CREATE_METHOD_TABLE(JSTestEventConstructorPrototype) };
JSObject* JSTestEventConstructorPrototype::self(ExecState* exec, JSGlobalObject* globalObject)
{
return getDOMPrototype<JSTestEventConstructor>(exec, globalObject);
}
-const ClassInfo JSTestEventConstructor::s_info = { "TestEventConstructor", &JSDOMWrapper::s_info, &JSTestEventConstructorTable, 0 , CREATE_METHOD_TABLE(JSTestEventConstructor) };
+const ClassInfo JSTestEventConstructor::s_info = { "TestEventConstructor", &Base::s_info, &JSTestEventConstructorTable, 0 , CREATE_METHOD_TABLE(JSTestEventConstructor) };
JSTestEventConstructor::JSTestEventConstructor(Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<TestEventConstructor> impl)
: JSDOMWrapper(structure, globalObject)
namespace WebCore {
ASSERT_CLASS_FITS_IN_CELL(JSTestInterface);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSTestInterface);
/* Hash table */
};
static const HashTable JSTestInterfaceConstructorTable = { 1, 0, JSTestInterfaceConstructorTableValues, 0 };
-const ClassInfo JSTestInterfaceConstructor::s_info = { "TestInterfaceConstructor", &DOMConstructorObject::s_info, &JSTestInterfaceConstructorTable, 0, CREATE_METHOD_TABLE(JSTestInterfaceConstructor) };
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSTestInterfaceConstructor);
+
+const ClassInfo JSTestInterfaceConstructor::s_info = { "TestInterfaceConstructor", &Base::s_info, &JSTestInterfaceConstructorTable, 0, CREATE_METHOD_TABLE(JSTestInterfaceConstructor) };
JSTestInterfaceConstructor::JSTestInterfaceConstructor(Structure* structure, JSDOMGlobalObject* globalObject)
: DOMConstructorObject(structure, globalObject)
};
static const HashTable JSTestInterfacePrototypeTable = { 1, 0, JSTestInterfacePrototypeTableValues, 0 };
-const ClassInfo JSTestInterfacePrototype::s_info = { "TestInterfacePrototype", &JSC::JSNonFinalObject::s_info, &JSTestInterfacePrototypeTable, 0, CREATE_METHOD_TABLE(JSTestInterfacePrototype) };
+const ClassInfo JSTestInterfacePrototype::s_info = { "TestInterfacePrototype", &Base::s_info, &JSTestInterfacePrototypeTable, 0, CREATE_METHOD_TABLE(JSTestInterfacePrototype) };
JSObject* JSTestInterfacePrototype::self(ExecState* exec, JSGlobalObject* globalObject)
{
return getDOMPrototype<JSTestInterface>(exec, globalObject);
}
-const ClassInfo JSTestInterface::s_info = { "TestInterface", &JSDOMWrapper::s_info, &JSTestInterfaceTable, 0 , CREATE_METHOD_TABLE(JSTestInterface) };
+const ClassInfo JSTestInterface::s_info = { "TestInterface", &Base::s_info, &JSTestInterfaceTable, 0 , CREATE_METHOD_TABLE(JSTestInterface) };
JSTestInterface::JSTestInterface(Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<TestInterface> impl)
: JSDOMWrapper(structure, globalObject)
namespace WebCore {
ASSERT_CLASS_FITS_IN_CELL(JSTestMediaQueryListListener);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSTestMediaQueryListListener);
/* Hash table */