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.

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: http://svn.webkit.org/repository/webkit/trunk@103083 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp
index 9836a12..d1195fb 100644
--- a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp
@@ -41,6 +41,8 @@
 
 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
diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
index b784413..d8d14f3 100644
--- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -170,7 +170,7 @@
 {
     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);
@@ -300,7 +300,7 @@
         separator = exec->argument(0).toString(exec);
 
     unsigned k = 0;
-    if (isJSArray(&exec->globalData(), thisObj)) {
+    if (isJSArray(thisObj)) {
         JSArray* array = asArray(thisObj);
 
         if (length) {
@@ -388,7 +388,7 @@
 {
     JSValue thisValue = exec->hostThisValue();
 
-    if (isJSArray(&exec->globalData(), thisValue))
+    if (isJSArray(thisValue))
         return JSValue::encode(asArray(thisValue)->pop());
 
     JSObject* thisObj = thisValue.toObject(exec);
@@ -412,7 +412,7 @@
 {
     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()));
@@ -481,7 +481,7 @@
         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++) {
@@ -627,7 +627,7 @@
     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) {
@@ -643,7 +643,7 @@
                     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) {
@@ -676,7 +676,7 @@
 
     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) {
@@ -715,7 +715,7 @@
 
     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);
@@ -773,7 +773,7 @@
 
     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);
@@ -836,7 +836,7 @@
     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);
@@ -892,7 +892,7 @@
     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);
@@ -944,7 +944,7 @@
     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);
@@ -1002,7 +1002,7 @@
         return throwVMTypeError(exec);
 
     JSArray* array = 0;
-    if (isJSArray(&exec->globalData(), thisObj))
+    if (isJSArray(thisObj))
         array = asArray(thisObj);
 
     if (exec->argumentCount() >= 2)
@@ -1079,7 +1079,7 @@
         return throwVMTypeError(exec);
 
     JSArray* array = 0;
-    if (isJSArray(&exec->globalData(), thisObj))
+    if (isJSArray(thisObj))
         array = asArray(thisObj);
     
     if (exec->argumentCount() >= 2)
diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp
index dc28de1..a54d281 100644
--- a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp
@@ -27,6 +27,7 @@
 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) };
 
diff --git a/Source/JavaScriptCore/runtime/BooleanObject.cpp b/Source/JavaScriptCore/runtime/BooleanObject.cpp
index 5a449c0..37c6eab 100644
--- a/Source/JavaScriptCore/runtime/BooleanObject.cpp
+++ b/Source/JavaScriptCore/runtime/BooleanObject.cpp
@@ -24,6 +24,7 @@
 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) };
 
diff --git a/Source/JavaScriptCore/runtime/BooleanPrototype.cpp b/Source/JavaScriptCore/runtime/BooleanPrototype.cpp
index c7ea964..b9605d0 100644
--- a/Source/JavaScriptCore/runtime/BooleanPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/BooleanPrototype.cpp
@@ -48,6 +48,7 @@
 */
 
 ASSERT_CLASS_FITS_IN_CELL(BooleanPrototype);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(BooleanPrototype);
 
 BooleanPrototype::BooleanPrototype(ExecState* exec, Structure* structure)
     : BooleanObject(exec->globalData(), structure)
diff --git a/Source/JavaScriptCore/runtime/ClassInfo.h b/Source/JavaScriptCore/runtime/ClassInfo.h
index 09fedb3..9fff64e 100644
--- a/Source/JavaScriptCore/runtime/ClassInfo.h
+++ b/Source/JavaScriptCore/runtime/ClassInfo.h
@@ -33,6 +33,9 @@
     struct HashTable;
 
     struct MethodTable {
+        typedef void (*DestroyFunctionPtr)(JSCell*);
+        DestroyFunctionPtr destroy;
+
         typedef void (*VisitChildrenFunctionPtr)(JSCell*, SlotVisitor&);
         VisitChildrenFunctionPtr visitChildren;
 
@@ -114,6 +117,7 @@
 #define HAS_MEMBER_NAMED(klass, name) (MemberCheck##name<klass>::has)
 
 #define CREATE_METHOD_TABLE(ClassName) { \
+        &ClassName::destroy, \
         &ClassName::visitChildren, \
         &ClassName::getCallData, \
         &ClassName::getConstructData, \
diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp
index 931899e..ad402c7 100644
--- a/Source/JavaScriptCore/runtime/DateConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp
@@ -72,6 +72,7 @@
 */
 
 ASSERT_CLASS_FITS_IN_CELL(DateConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(DateConstructor);
 
 DateConstructor::DateConstructor(JSGlobalObject* globalObject, Structure* structure)
     : InternalFunction(globalObject, structure) 
diff --git a/Source/JavaScriptCore/runtime/DateInstance.cpp b/Source/JavaScriptCore/runtime/DateInstance.cpp
index 545757b..a502770 100644
--- a/Source/JavaScriptCore/runtime/DateInstance.cpp
+++ b/Source/JavaScriptCore/runtime/DateInstance.cpp
@@ -53,6 +53,11 @@
     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();
diff --git a/Source/JavaScriptCore/runtime/DateInstance.h b/Source/JavaScriptCore/runtime/DateInstance.h
index 324170b..8d90cf0 100644
--- a/Source/JavaScriptCore/runtime/DateInstance.h
+++ b/Source/JavaScriptCore/runtime/DateInstance.h
@@ -34,7 +34,9 @@
         DateInstance(ExecState*, Structure*);
         void finishCreation(JSGlobalData&);
         void finishCreation(JSGlobalData&, double);
-        
+
+        static void destroy(JSCell*);
+ 
     public:
         typedef JSWrapperObject Base;
 
diff --git a/Source/JavaScriptCore/runtime/Error.cpp b/Source/JavaScriptCore/runtime/Error.cpp
index 4a1e148..a5373d5 100644
--- a/Source/JavaScriptCore/runtime/Error.cpp
+++ b/Source/JavaScriptCore/runtime/Error.cpp
@@ -170,6 +170,11 @@
 
 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();
diff --git a/Source/JavaScriptCore/runtime/Error.h b/Source/JavaScriptCore/runtime/Error.h
index ac7354d..17c3498 100644
--- a/Source/JavaScriptCore/runtime/Error.h
+++ b/Source/JavaScriptCore/runtime/Error.h
@@ -82,6 +82,8 @@
         {
         }
 
+        static void destroy(JSCell*);
+
     public:
         typedef InternalFunction Base;
 
diff --git a/Source/JavaScriptCore/runtime/ErrorConstructor.cpp b/Source/JavaScriptCore/runtime/ErrorConstructor.cpp
index 52309d1..c8f93ba 100644
--- a/Source/JavaScriptCore/runtime/ErrorConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/ErrorConstructor.cpp
@@ -28,6 +28,7 @@
 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) };
 
diff --git a/Source/JavaScriptCore/runtime/ErrorInstance.cpp b/Source/JavaScriptCore/runtime/ErrorInstance.cpp
index 83abe5c..91a6fc4 100644
--- a/Source/JavaScriptCore/runtime/ErrorInstance.cpp
+++ b/Source/JavaScriptCore/runtime/ErrorInstance.cpp
@@ -23,6 +23,8 @@
 
 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)
diff --git a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
index d5ace80..05e971f 100644
--- a/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
+++ b/Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
@@ -41,6 +41,8 @@
 
 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)
@@ -66,6 +68,8 @@
 }
 
 
+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)
diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp
index 64e92e8..ad86463 100644
--- a/Source/JavaScriptCore/runtime/Executable.cpp
+++ b/Source/JavaScriptCore/runtime/Executable.cpp
@@ -38,6 +38,11 @@
 
 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)
@@ -61,8 +66,9 @@
 
 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)
@@ -93,6 +99,11 @@
 
 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)
@@ -100,8 +111,9 @@
 {
 }
 
-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) };
@@ -111,8 +123,9 @@
 {
 }
 
-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) };
@@ -137,8 +150,9 @@
 {
 }
 
-FunctionExecutable::~FunctionExecutable()
+void FunctionExecutable::destroy(JSCell* cell)
 {
+    jsCast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();
 }
 
 JSObject* EvalExecutable::compileOptimized(ExecState* exec, ScopeChainNode* scopeChainNode)
diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h
index 6395843..7f85c90 100644
--- a/Source/JavaScriptCore/runtime/Executable.h
+++ b/Source/JavaScriptCore/runtime/Executable.h
@@ -77,6 +77,8 @@
     public:
         typedef JSCell Base;
 
+        static void destroy(JSCell*);
+
         bool isHostFunction() const
         {
             ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
@@ -206,7 +208,7 @@
         }
 #endif
 
-        virtual ~NativeExecutable();
+        static void destroy(JSCell*);
 
         NativeFunction function() { return m_function; }
         NativeFunction constructor() { return m_constructor; }
@@ -274,6 +276,8 @@
         {
         }
 
+        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(); }
@@ -318,7 +322,7 @@
     public:
         typedef ScriptExecutable Base;
 
-        virtual ~EvalExecutable();
+        static void destroy(JSCell*);
 
         JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
         {
@@ -391,7 +395,7 @@
             return executable;
         }
 
-        virtual ~ProgramExecutable();
+        static void destroy(JSCell*);
 
         JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
         {
@@ -468,7 +472,7 @@
             return executable;
         }
 
-        virtual ~FunctionExecutable();
+        static void destroy(JSCell*);
 
         JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain)
         {
diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
index be4c63c..e08e58c 100644
--- a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp
@@ -36,6 +36,7 @@
 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) };
 
diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
index 1989827..b1017e4 100644
--- a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
@@ -33,6 +33,7 @@
 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) };
 
@@ -136,7 +137,7 @@
             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);
diff --git a/Source/JavaScriptCore/runtime/GetterSetter.cpp b/Source/JavaScriptCore/runtime/GetterSetter.cpp
index 17cbb44..920399d 100644
--- a/Source/JavaScriptCore/runtime/GetterSetter.cpp
+++ b/Source/JavaScriptCore/runtime/GetterSetter.cpp
@@ -28,6 +28,8 @@
 
 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)
diff --git a/Source/JavaScriptCore/runtime/InitializeThreading.cpp b/Source/JavaScriptCore/runtime/InitializeThreading.cpp
index 6989572..2b874c7 100644
--- a/Source/JavaScriptCore/runtime/InitializeThreading.cpp
+++ b/Source/JavaScriptCore/runtime/InitializeThreading.cpp
@@ -57,7 +57,6 @@
 #if ENABLE(WRITE_BARRIER_PROFILING)
     WriteBarrierCounters::initialize();
 #endif
-    JSGlobalData::storeVPtrs();
 #if ENABLE(JIT) && ENABLE(ASSEMBLER)
     ExecutableAllocator::initializeAllocator();
 #endif
diff --git a/Source/JavaScriptCore/runtime/InternalFunction.cpp b/Source/JavaScriptCore/runtime/InternalFunction.cpp
index 1714163..50ea504 100644
--- a/Source/JavaScriptCore/runtime/InternalFunction.cpp
+++ b/Source/JavaScriptCore/runtime/InternalFunction.cpp
@@ -29,18 +29,11 @@
 
 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)
 {
@@ -63,7 +56,7 @@
 {
     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();
diff --git a/Source/JavaScriptCore/runtime/InternalFunction.h b/Source/JavaScriptCore/runtime/InternalFunction.h
index 8e2178e..a038b7a 100644
--- a/Source/JavaScriptCore/runtime/InternalFunction.h
+++ b/Source/JavaScriptCore/runtime/InternalFunction.h
@@ -49,17 +49,11 @@
     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);
diff --git a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.cpp b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.cpp
index b1b33f5..8517085 100644
--- a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.cpp
+++ b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.cpp
@@ -28,6 +28,8 @@
 
 namespace JSC {
 
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSAPIValueWrapper);
+
 const ClassInfo JSAPIValueWrapper::s_info = { "API Wrapper", 0, 0, 0, CREATE_METHOD_TABLE(JSAPIValueWrapper) };
 
 } // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp
index f756c7b..0c9220e 100644
--- a/Source/JavaScriptCore/runtime/JSArray.cpp
+++ b/Source/JavaScriptCore/runtime/JSArray.cpp
@@ -126,11 +126,6 @@
 
 #endif
 
-JSArray::JSArray(VPtrStealingHackType)
-    : JSNonFinalObject(VPtrStealingHack)
-{
-}
-
 JSArray::JSArray(JSGlobalData& globalData, Structure* structure)
     : JSNonFinalObject(globalData, structure)
 {
@@ -277,13 +272,18 @@
 
 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);
diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h
index e958d55..1ead82c 100644
--- a/Source/JavaScriptCore/runtime/JSArray.h
+++ b/Source/JavaScriptCore/runtime/JSArray.h
@@ -71,8 +71,8 @@
     public:
         typedef JSNonFinalObject Base;
 
-        JSArray(VPtrStealingHackType);
-        virtual ~JSArray();
+        ~JSArray();
+        static void destroy(JSCell*);
 
         static JSArray* create(JSGlobalData& globalData, Structure* structure)
         {
@@ -216,8 +216,8 @@
         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.
diff --git a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp
index cf0ba83..0e5a99a 100644
--- a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp
+++ b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp
@@ -31,6 +31,7 @@
 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) };
 
@@ -38,7 +39,7 @@
 {
     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;
@@ -58,7 +59,7 @@
 {
     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;
diff --git a/Source/JavaScriptCore/runtime/JSByteArray.cpp b/Source/JavaScriptCore/runtime/JSByteArray.cpp
index 9973c56..7478a08 100644
--- a/Source/JavaScriptCore/runtime/JSByteArray.cpp
+++ b/Source/JavaScriptCore/runtime/JSByteArray.cpp
@@ -41,13 +41,15 @@
 {
 }
         
-#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)
 {
diff --git a/Source/JavaScriptCore/runtime/JSByteArray.h b/Source/JavaScriptCore/runtime/JSByteArray.h
index 0041d14..5122bad 100644
--- a/Source/JavaScriptCore/runtime/JSByteArray.h
+++ b/Source/JavaScriptCore/runtime/JSByteArray.h
@@ -102,9 +102,8 @@
 
         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); }
 
@@ -118,11 +117,6 @@
         }
 
     private:
-        JSByteArray(VPtrStealingHackType)
-            : JSNonFinalObject(VPtrStealingHack)
-        {
-        }
-
         RefPtr<WTF::ByteArray> m_storage;
     };
     
@@ -132,7 +126,7 @@
         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
 
diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp
index 491ef08..065fd13 100644
--- a/Source/JavaScriptCore/runtime/JSCell.cpp
+++ b/Source/JavaScriptCore/runtime/JSCell.cpp
@@ -31,6 +31,13 @@
 
 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())
diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h
index 76cef04..c755a60 100644
--- a/Source/JavaScriptCore/runtime/JSCell.h
+++ b/Source/JavaScriptCore/runtime/JSCell.h
@@ -65,15 +65,12 @@
         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.
@@ -108,6 +105,7 @@
 
         // 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);
@@ -117,8 +115,6 @@
 
         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); }
 
@@ -133,6 +129,11 @@
         {
             return OBJECT_OFFSETOF(JSCell, m_structure);
         }
+
+        static ptrdiff_t classInfoOffset()
+        {
+            return OBJECT_OFFSETOF(JSCell, m_classInfo);
+        }
         
         void* structureAddress()
         {
@@ -166,13 +167,9 @@
         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)
     {
@@ -189,27 +186,16 @@
         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 const ClassInfo* JSCell::classInfo() const
+    {
+        return m_classInfo;
+    }
+
     inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
     {
         visitor.append(&cell->m_structure);
diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp
index 0812f21..4e05535 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.cpp
+++ b/Source/JavaScriptCore/runtime/JSFunction.cpp
@@ -73,11 +73,6 @@
     return function;
 }
 
-JSFunction::JSFunction(VPtrStealingHackType)
-    : Base(VPtrStealingHack)
-{
-}
-
 JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
     : Base(exec->globalData(), structure)
     , m_executable()
@@ -113,14 +108,11 @@
     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)
@@ -138,7 +130,7 @@
 {
     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();
diff --git a/Source/JavaScriptCore/runtime/JSFunction.h b/Source/JavaScriptCore/runtime/JSFunction.h
index b75332a..988ae12 100644
--- a/Source/JavaScriptCore/runtime/JSFunction.h
+++ b/Source/JavaScriptCore/runtime/JSFunction.h
@@ -35,7 +35,6 @@
     class JSGlobalObject;
     class NativeExecutable;
     class SourceCode;
-    class VPtrHackExecutable;
     namespace DFG {
     class SpeculativeJIT;
     class JITCompiler;
@@ -65,8 +64,7 @@
             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*);
@@ -144,8 +142,6 @@
         static void visitChildren(JSCell*, SlotVisitor&);
 
     private:
-        explicit JSFunction(VPtrStealingHackType);
-
         bool isHostFunctionNonInline() const;
 
         static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
index a535fc2..22e7693 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -109,12 +109,6 @@
 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 { \
@@ -124,52 +118,6 @@
 #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)
diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h
index 139dd42..1619f92 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalData.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalData.h
@@ -105,18 +105,18 @@
 
     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;
     };
@@ -193,13 +193,6 @@
         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.
@@ -340,7 +333,7 @@
 #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; }
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
index 342985c..420bc89 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -122,6 +122,11 @@
     }
 }
 
+void JSGlobalObject::destroy(JSCell* cell)
+{
+    jsCast<JSGlobalObject*>(cell)->JSGlobalObject::~JSGlobalObject();
+}
+
 void JSGlobalObject::init(JSObject* thisValue)
 {
     ASSERT(JSLock::currentThreadIsHoldingLock());
diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h
index 3f93cd8..782e3a3 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h
@@ -193,7 +193,8 @@
         }
 
     public:
-        virtual ~JSGlobalObject();
+        ~JSGlobalObject();
+        static void destroy(JSCell*);
 
         static void visitChildren(JSCell*, SlotVisitor&);
 
diff --git a/Source/JavaScriptCore/runtime/JSGlobalThis.cpp b/Source/JavaScriptCore/runtime/JSGlobalThis.cpp
index 85bfb7a..8b2a7a1 100644
--- a/Source/JavaScriptCore/runtime/JSGlobalThis.cpp
+++ b/Source/JavaScriptCore/runtime/JSGlobalThis.cpp
@@ -31,6 +31,7 @@
 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) };
 
diff --git a/Source/JavaScriptCore/runtime/JSNotAnObject.cpp b/Source/JavaScriptCore/runtime/JSNotAnObject.cpp
index 91f90d6..6824002 100644
--- a/Source/JavaScriptCore/runtime/JSNotAnObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSNotAnObject.cpp
@@ -35,6 +35,7 @@
 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) };
 
diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp
index ea4c1ad..05c6c29 100644
--- a/Source/JavaScriptCore/runtime/JSONObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSONObject.cpp
@@ -43,6 +43,7 @@
 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*);
@@ -495,7 +496,7 @@
     // 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 {
@@ -669,7 +670,7 @@
             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));
 
@@ -694,7 +695,7 @@
                     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;
@@ -717,7 +718,7 @@
                 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);
@@ -730,7 +731,7 @@
             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));
 
@@ -797,7 +798,7 @@
                     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;
         }
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp
index 14f0935..9cc2961 100644
--- a/Source/JavaScriptCore/runtime/JSObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSObject.cpp
@@ -46,15 +46,22 @@
 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)
 {
-    printf("Something Visual Studio can't optimize away.\n");
+    jsCast<JSFinalObject*>(cell)->JSFinalObject::~JSFinalObject();
+}
+
+void JSNonFinalObject::destroy(JSCell* cell)
+{
+    jsCast<JSNonFinalObject*>(cell)->JSNonFinalObject::~JSNonFinalObject();
 }
 
 static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode)
@@ -81,8 +88,9 @@
     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)
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h
index f568d42..363ec30 100644
--- a/Source/JavaScriptCore/runtime/JSObject.h
+++ b/Source/JavaScriptCore/runtime/JSObject.h
@@ -80,7 +80,7 @@
     public:
         typedef JSCell Base;
 
-        virtual void vtableAnchor();
+        static void destroy(JSCell*);
 
         static void visitChildren(JSCell*, SlotVisitor&);
 
@@ -243,6 +243,7 @@
             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)
@@ -255,11 +256,6 @@
         // 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.
@@ -319,12 +315,9 @@
             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)
         {
@@ -335,6 +328,7 @@
             Base::finishCreation(globalData, m_inlineStorage);
             ASSERT(!(OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage) % sizeof(double)));
             ASSERT(this->structure()->propertyStorageCapacity() == JSNonFinalObject_inlineStorageCapacity);
+            ASSERT(classInfo());
         }
 
     private:
@@ -349,11 +343,6 @@
     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);
@@ -374,21 +363,32 @@
             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));
diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
index f431042..7207a4c 100644
--- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
+++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
@@ -81,6 +81,11 @@
     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();
diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
index 97a5032..ce2e44e 100644
--- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
+++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
@@ -52,7 +52,9 @@
             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);
diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
index d90c68c..3084f3f 100644
--- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp
@@ -34,6 +34,11 @@
 
 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);
diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h
index 23a3aca..de0b816 100644
--- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h
+++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h
@@ -67,7 +67,9 @@
             : 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;
     };
diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp
index 0e6a48a..62cc55c 100644
--- a/Source/JavaScriptCore/runtime/JSString.cpp
+++ b/Source/JavaScriptCore/runtime/JSString.cpp
@@ -45,9 +45,10 @@
     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)
diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h
index 7cf8382..d51a23f 100644
--- a/Source/JavaScriptCore/runtime/JSString.h
+++ b/Source/JavaScriptCore/runtime/JSString.h
@@ -69,6 +69,8 @@
 
         typedef JSCell Base;
 
+        static void destroy(JSCell*);
+
         class RopeBuilder {
         public:
             RopeBuilder(JSGlobalData& globalData)
@@ -197,8 +199,6 @@
             return newString;
         }
 
-        virtual ~JSString();
-
         const UString& value(ExecState* exec) const
         {
             if (isRope())
@@ -243,11 +243,6 @@
         static void visitChildren(JSCell*, SlotVisitor&);
 
     private:
-        JSString(VPtrStealingHackType) 
-            : JSCell(VPtrStealingHack)
-        {
-        }
-
         void resolveRope(ExecState*) const;
         void resolveRopeSlowCase8(LChar*) const;
         void resolveRopeSlowCase(UChar*) const;
@@ -279,16 +274,6 @@
 
     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());
@@ -304,7 +289,7 @@
     {
         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)
@@ -314,7 +299,7 @@
         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)
@@ -322,13 +307,13 @@
         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)
@@ -350,7 +335,7 @@
             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)
@@ -376,7 +361,7 @@
             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)
@@ -391,7 +376,7 @@
             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)
@@ -404,12 +389,12 @@
             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()); }
@@ -448,7 +433,7 @@
         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
     {
diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.cpp b/Source/JavaScriptCore/runtime/JSVariableObject.cpp
index 9f38ea9..706e3de 100644
--- a/Source/JavaScriptCore/runtime/JSVariableObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSVariableObject.cpp
@@ -37,8 +37,9 @@
 
 namespace JSC {
 
-JSVariableObject::~JSVariableObject()
+void JSVariableObject::destroy(JSCell* cell)
 {
+    jsCast<JSVariableObject*>(cell)->JSVariableObject::~JSVariableObject();
 }
 
 bool JSVariableObject::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h
index e49fb71..8a5c5a0 100644
--- a/Source/JavaScriptCore/runtime/JSVariableObject.h
+++ b/Source/JavaScriptCore/runtime/JSVariableObject.h
@@ -48,7 +48,7 @@
 
         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);
 
diff --git a/Source/JavaScriptCore/runtime/JSWrapperObject.cpp b/Source/JavaScriptCore/runtime/JSWrapperObject.cpp
index ca5bd87..f8f5727 100644
--- a/Source/JavaScriptCore/runtime/JSWrapperObject.cpp
+++ b/Source/JavaScriptCore/runtime/JSWrapperObject.cpp
@@ -25,10 +25,7 @@
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject);
-
-JSWrapperObject::~JSWrapperObject()
-{
-}
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(JSWrapperObject);
 
 void JSWrapperObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
diff --git a/Source/JavaScriptCore/runtime/JSWrapperObject.h b/Source/JavaScriptCore/runtime/JSWrapperObject.h
index 73713c0..65b4bdb 100644
--- a/Source/JavaScriptCore/runtime/JSWrapperObject.h
+++ b/Source/JavaScriptCore/runtime/JSWrapperObject.h
@@ -46,8 +46,6 @@
 
         static void visitChildren(JSCell*, SlotVisitor&);
 
-        virtual ~JSWrapperObject();
-        
     private:
         WriteBarrier<Unknown> m_internalValue;
     };
diff --git a/Source/JavaScriptCore/runtime/MathObject.cpp b/Source/JavaScriptCore/runtime/MathObject.cpp
index 006559d..58b0912 100644
--- a/Source/JavaScriptCore/runtime/MathObject.cpp
+++ b/Source/JavaScriptCore/runtime/MathObject.cpp
@@ -59,6 +59,8 @@
 
 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
diff --git a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
index dde9278..b6aff91 100644
--- a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp
@@ -29,6 +29,7 @@
 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) };
 
diff --git a/Source/JavaScriptCore/runtime/NumberConstructor.cpp b/Source/JavaScriptCore/runtime/NumberConstructor.cpp
index 084c63f..e863e86 100644
--- a/Source/JavaScriptCore/runtime/NumberConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/NumberConstructor.cpp
@@ -42,6 +42,8 @@
 
 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
diff --git a/Source/JavaScriptCore/runtime/NumberObject.cpp b/Source/JavaScriptCore/runtime/NumberObject.cpp
index b751053..1fea254 100644
--- a/Source/JavaScriptCore/runtime/NumberObject.cpp
+++ b/Source/JavaScriptCore/runtime/NumberObject.cpp
@@ -28,6 +28,7 @@
 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) };
 
diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.cpp b/Source/JavaScriptCore/runtime/NumberPrototype.cpp
index 3bcb9bb..4612b56 100644
--- a/Source/JavaScriptCore/runtime/NumberPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/NumberPrototype.cpp
@@ -69,6 +69,7 @@
 */
 
 ASSERT_CLASS_FITS_IN_CELL(NumberPrototype);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(NumberPrototype);
 
 NumberPrototype::NumberPrototype(ExecState* exec, Structure* structure)
     : NumberObject(exec->globalData(), structure)
diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
index 5952ce8..65d28c1 100644
--- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
@@ -55,6 +55,8 @@
 
 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
diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
index a1e4966..3f4dc19 100644
--- a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp
@@ -44,6 +44,8 @@
 
 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
diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h
index 97dae3e..ca2174f 100644
--- a/Source/JavaScriptCore/runtime/Operations.h
+++ b/Source/JavaScriptCore/runtime/Operations.h
@@ -47,7 +47,7 @@
         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)
@@ -69,7 +69,7 @@
         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)
@@ -230,8 +230,7 @@
         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;
@@ -265,8 +264,7 @@
         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;
diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp
index 05df32b..594b225 100644
--- a/Source/JavaScriptCore/runtime/RegExp.cpp
+++ b/Source/JavaScriptCore/runtime/RegExp.cpp
@@ -248,11 +248,13 @@
         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)
diff --git a/Source/JavaScriptCore/runtime/RegExp.h b/Source/JavaScriptCore/runtime/RegExp.h
index aa3a61f..65eb484 100644
--- a/Source/JavaScriptCore/runtime/RegExp.h
+++ b/Source/JavaScriptCore/runtime/RegExp.h
@@ -42,7 +42,7 @@
         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; }
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
index 03d2fd2..a287377 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -115,6 +115,11 @@
     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())
 {
@@ -140,6 +145,11 @@
     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());
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.h b/Source/JavaScriptCore/runtime/RegExpConstructor.h
index 5f930eb..7fb88d2 100644
--- a/Source/JavaScriptCore/runtime/RegExpConstructor.h
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.h
@@ -98,6 +98,7 @@
 
     private:
         RegExpConstructor(JSGlobalObject*, Structure*);
+        static void destroy(JSCell*);
         static ConstructType getConstructData(JSCell*, ConstructData&);
         static CallType getCallData(JSCell*, CallData&);
 
diff --git a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
index 1cc898e..1c117b0 100644
--- a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
+++ b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h
@@ -37,7 +37,8 @@
             regExp->finishCreation(exec->globalData(), ctorPrivate);
             return regExp;
         }
-        virtual ~RegExpMatchesArray();
+        ~RegExpMatchesArray();
+        static void destroy(JSCell*);
 
         static JS_EXPORTDATA const ClassInfo s_info;
         
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp
index 7213dc2..4553f7a 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp
@@ -75,8 +75,9 @@
     ASSERT(inherits(&s_info));
 }
 
-RegExpObject::~RegExpObject()
+void RegExpObject::destroy(JSCell* cell)
 {
+    jsCast<RegExpObject*>(cell)->RegExpObject::~RegExpObject();
 }
 
 void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.h b/Source/JavaScriptCore/runtime/RegExpObject.h
index a117f36..ee98b66 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.h
+++ b/Source/JavaScriptCore/runtime/RegExpObject.h
@@ -44,8 +44,6 @@
             return object;
         }
 
-        virtual ~RegExpObject();
-
         void setRegExp(JSGlobalData& globalData, RegExp* r) { d->regExp.set(globalData, this, r); }
         RegExp* regExp() const { return d->regExp.get(); }
 
@@ -79,6 +77,8 @@
     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&);
diff --git a/Source/JavaScriptCore/runtime/ScopeChain.cpp b/Source/JavaScriptCore/runtime/ScopeChain.cpp
index 79f2a7a..099f7fd 100644
--- a/Source/JavaScriptCore/runtime/ScopeChain.cpp
+++ b/Source/JavaScriptCore/runtime/ScopeChain.cpp
@@ -29,9 +29,7 @@
 
 namespace JSC {
 
-ScopeChainNode::~ScopeChainNode()
-{
-}
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(ScopeChainNode);
 
 #ifndef NDEBUG
 
diff --git a/Source/JavaScriptCore/runtime/ScopeChain.h b/Source/JavaScriptCore/runtime/ScopeChain.h
index 48385d0..fde690e 100644
--- a/Source/JavaScriptCore/runtime/ScopeChain.h
+++ b/Source/JavaScriptCore/runtime/ScopeChain.h
@@ -45,8 +45,6 @@
         {
         }
 
-        virtual ~ScopeChainNode();
-
     protected:
         void finishCreation(JSGlobalData* globalData, JSGlobalObject* globalObject)
         {
diff --git a/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp b/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp
index 21283db..fbd9d5f 100644
--- a/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp
+++ b/Source/JavaScriptCore/runtime/StrictEvalActivation.cpp
@@ -28,6 +28,8 @@
 
 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)
diff --git a/Source/JavaScriptCore/runtime/StringConstructor.cpp b/Source/JavaScriptCore/runtime/StringConstructor.cpp
index 96570b2..d2f75a0 100644
--- a/Source/JavaScriptCore/runtime/StringConstructor.cpp
+++ b/Source/JavaScriptCore/runtime/StringConstructor.cpp
@@ -46,6 +46,7 @@
 */
 
 ASSERT_CLASS_FITS_IN_CELL(StringConstructor);
+ASSERT_HAS_TRIVIAL_DESTRUCTOR(StringConstructor);
 
 StringConstructor::StringConstructor(JSGlobalObject* globalObject, Structure* structure)
     : InternalFunction(globalObject, structure)
diff --git a/Source/JavaScriptCore/runtime/StringObject.cpp b/Source/JavaScriptCore/runtime/StringObject.cpp
index 3eed267..4a24698 100644
--- a/Source/JavaScriptCore/runtime/StringObject.cpp
+++ b/Source/JavaScriptCore/runtime/StringObject.cpp
@@ -26,6 +26,7 @@
 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) };
 
@@ -34,10 +35,6 @@
 {
 }
 
-void StringObject::vtableAnchor()
-{
-}
-
 void StringObject::finishCreation(JSGlobalData& globalData, JSString* string)
 {
     Base::finishCreation(globalData);
diff --git a/Source/JavaScriptCore/runtime/StringObject.h b/Source/JavaScriptCore/runtime/StringObject.h
index d65ecc5..806d07b 100644
--- a/Source/JavaScriptCore/runtime/StringObject.h
+++ b/Source/JavaScriptCore/runtime/StringObject.h
@@ -30,8 +30,6 @@
     public:
         typedef JSWrapperObject Base;
 
-        virtual void vtableAnchor();
-
         static StringObject* create(ExecState* exec, Structure* structure)
         {
             JSString* string = jsEmptyString(exec);
diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp
index 3de8953..9bf18de 100644
--- a/Source/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp
@@ -45,6 +45,7 @@
 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*);
diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp
index 6b4ca2b..dda8c73 100644
--- a/Source/JavaScriptCore/runtime/Structure.cpp
+++ b/Source/JavaScriptCore/runtime/Structure.cpp
@@ -218,8 +218,9 @@
         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)
diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h
index e372b20..92e1b3b 100644
--- a/Source/JavaScriptCore/runtime/Structure.h
+++ b/Source/JavaScriptCore/runtime/Structure.h
@@ -103,7 +103,7 @@
 
         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);
@@ -335,16 +335,18 @@
     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)
@@ -380,6 +382,25 @@
         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
diff --git a/Source/JavaScriptCore/runtime/StructureChain.cpp b/Source/JavaScriptCore/runtime/StructureChain.cpp
index 3a08569..afb2d95 100644
--- a/Source/JavaScriptCore/runtime/StructureChain.cpp
+++ b/Source/JavaScriptCore/runtime/StructureChain.cpp
@@ -39,8 +39,9 @@
 {
 }
 
-StructureChain::~StructureChain()
+void StructureChain::destroy(JSCell* cell)
 {
+    jsCast<StructureChain*>(cell)->StructureChain::~StructureChain();
 }
 
 void StructureChain::visitChildren(JSCell* cell, SlotVisitor& visitor)
diff --git a/Source/JavaScriptCore/runtime/StructureChain.h b/Source/JavaScriptCore/runtime/StructureChain.h
index 281f602..01a59bf 100644
--- a/Source/JavaScriptCore/runtime/StructureChain.h
+++ b/Source/JavaScriptCore/runtime/StructureChain.h
@@ -75,7 +75,7 @@
 
     private:
         StructureChain(JSGlobalData&, Structure*);
-        ~StructureChain();
+        static void destroy(JSCell*);
         OwnArrayPtr<WriteBarrier<Structure> > m_vector;
     };