diff options
author | Steve Block <steveblock@google.com> | 2011-05-25 19:08:45 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-06-08 13:51:31 +0100 |
commit | 2bde8e466a4451c7319e3a072d118917957d6554 (patch) | |
tree | 28f4a1b869a513e565c7760d0e6a06e7cf1fe95a /Source/JavaScriptCore | |
parent | 6939c99b71d9372d14a0c74a772108052e8c48c8 (diff) | |
download | external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.zip external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.tar.gz external_webkit-2bde8e466a4451c7319e3a072d118917957d6554.tar.bz2 |
Merge WebKit at r82507: Initial merge by git
Change-Id: I60ce9d780725b58b45e54165733a8ffee23b683e
Diffstat (limited to 'Source/JavaScriptCore')
290 files changed, 14905 insertions, 3107 deletions
diff --git a/Source/JavaScriptCore/API/APIShims.h b/Source/JavaScriptCore/API/APIShims.h index 26db2dc..2e13851 100644 --- a/Source/JavaScriptCore/API/APIShims.h +++ b/Source/JavaScriptCore/API/APIShims.h @@ -42,7 +42,7 @@ protected: UNUSED_PARAM(registerThread); #if ENABLE(JSC_MULTIPLE_THREADS) if (registerThread) - globalData->heap.machineStackMarker().registerThread(); + globalData->heap.machineThreads().addCurrentThread(); #endif m_globalData->heap.activityCallback()->synchronize(); m_globalData->timeoutChecker.start(); diff --git a/Source/JavaScriptCore/API/JSBase.h b/Source/JavaScriptCore/API/JSBase.h index d962b01..fed54fe 100644 --- a/Source/JavaScriptCore/API/JSBase.h +++ b/Source/JavaScriptCore/API/JSBase.h @@ -80,6 +80,11 @@ typedef struct OpaqueJSValue* JSObjectRef; #define JS_EXPORT #endif /* defined(JS_NO_EXPORT) */ +/* JS tests uses WTF but has no config.h, so we need to set the export defines here. */ +#ifndef WTF_EXPORT_PRIVATE +#define WTF_EXPORT_PRIVATE JS_EXPORT +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/Source/JavaScriptCore/API/JSCallbackConstructor.h b/Source/JavaScriptCore/API/JSCallbackConstructor.h index cd307a6..001c416 100644 --- a/Source/JavaScriptCore/API/JSCallbackConstructor.h +++ b/Source/JavaScriptCore/API/JSCallbackConstructor.h @@ -39,9 +39,9 @@ public: JSObjectCallAsConstructorCallback callback() const { return m_callback; } static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue proto) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: diff --git a/Source/JavaScriptCore/API/JSCallbackFunction.h b/Source/JavaScriptCore/API/JSCallbackFunction.h index d8ae608..11fb95c 100644 --- a/Source/JavaScriptCore/API/JSCallbackFunction.h +++ b/Source/JavaScriptCore/API/JSCallbackFunction.h @@ -39,9 +39,9 @@ public: // InternalFunction mish-mashes constructor and function behavior -- we should // refactor the code so this override isn't necessary - static PassRefPtr<Structure> createStructure(JSValue proto) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } private: diff --git a/Source/JavaScriptCore/API/JSCallbackObject.h b/Source/JavaScriptCore/API/JSCallbackObject.h index 732cc1d..a0adb44 100644 --- a/Source/JavaScriptCore/API/JSCallbackObject.h +++ b/Source/JavaScriptCore/API/JSCallbackObject.h @@ -128,9 +128,9 @@ public: JSClassRef classRef() const { return m_callbackObjectData->jsClass; } bool inherits(JSClassRef) const; - static PassRefPtr<Structure> createStructure(JSValue proto) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), Base::AnonymousSlotCount, &s_info); + return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), Base::AnonymousSlotCount, &s_info); } JSValue getPrivateProperty(const Identifier& propertyName) const diff --git a/Source/JavaScriptCore/API/JSClassRef.cpp b/Source/JavaScriptCore/API/JSClassRef.cpp index d953dce..70668bd 100644 --- a/Source/JavaScriptCore/API/JSClassRef.cpp +++ b/Source/JavaScriptCore/API/JSClassRef.cpp @@ -84,8 +84,9 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* // Use a local variable here to sidestep an RVCT compiler bug. StaticValueEntry* entry = new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes); StringImpl* impl = valueName.impl(); - impl->ref(); - m_staticValues->add(impl, entry); + StaticValueEntry* existingEntry = m_staticValues->get(impl); + m_staticValues->set(impl, entry); + delete existingEntry; } ++staticValue; } @@ -99,8 +100,9 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* // Use a local variable here to sidestep an RVCT compiler bug. StaticFunctionEntry* entry = new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes); StringImpl* impl = functionName.impl(); - impl->ref(); - m_staticFunctions->add(impl, entry); + StaticFunctionEntry* existingEntry = m_staticFunctions->get(impl); + m_staticFunctions->set(impl, entry); + delete existingEntry; } ++staticFunction; } diff --git a/Source/JavaScriptCore/API/JSClassRef.h b/Source/JavaScriptCore/API/JSClassRef.h index 0f4119a..239c5a4 100644 --- a/Source/JavaScriptCore/API/JSClassRef.h +++ b/Source/JavaScriptCore/API/JSClassRef.h @@ -85,7 +85,7 @@ public: JSC::WeakGCPtr<JSC::JSObject> cachedPrototype; }; -struct OpaqueJSClass : public ThreadSafeShared<OpaqueJSClass> { +struct OpaqueJSClass : public ThreadSafeRefCounted<OpaqueJSClass> { static PassRefPtr<OpaqueJSClass> create(const JSClassDefinition*); static PassRefPtr<OpaqueJSClass> createNoAutomaticPrototype(const JSClassDefinition*); ~OpaqueJSClass(); diff --git a/Source/JavaScriptCore/API/JSContextRef.cpp b/Source/JavaScriptCore/API/JSContextRef.cpp index ccab953..e5c778f 100644 --- a/Source/JavaScriptCore/API/JSContextRef.cpp +++ b/Source/JavaScriptCore/API/JSContextRef.cpp @@ -93,11 +93,11 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass #endif if (!globalObjectClass) { - JSGlobalObject* globalObject = new (globalData.get()) JSGlobalObject; + JSGlobalObject* globalObject = new (globalData.get()) JSGlobalObject(*globalData); return JSGlobalContextRetain(toGlobalRef(globalObject->globalExec())); } - JSGlobalObject* globalObject = new (globalData.get()) JSCallbackObject<JSGlobalObject>(globalObjectClass, JSCallbackObject<JSGlobalObject>::createStructure(jsNull())); + JSGlobalObject* globalObject = new (globalData.get()) JSCallbackObject<JSGlobalObject>(globalObjectClass, JSCallbackObject<JSGlobalObject>::createStructure(*globalData, jsNull())); ExecState* exec = globalObject->globalExec(); JSValue prototype = globalObjectClass->prototype(exec); if (!prototype) diff --git a/Source/JavaScriptCore/API/JSObjectRef.cpp b/Source/JavaScriptCore/API/JSObjectRef.cpp index 36ca338..b7030e4 100644 --- a/Source/JavaScriptCore/API/JSObjectRef.cpp +++ b/Source/JavaScriptCore/API/JSObjectRef.cpp @@ -124,7 +124,7 @@ JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned pa args.append(jsString(exec, parameterNames[i]->ustring())); args.append(jsString(exec, body->ustring())); - JSObject* result = constructFunction(exec, args, nameID, sourceURL->ustring(), startingLineNumber); + JSObject* result = constructFunction(exec, exec->lexicalGlobalObject(), args, nameID, sourceURL->ustring(), startingLineNumber); if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); @@ -168,7 +168,7 @@ JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSVal for (size_t i = 0; i < argumentCount; ++i) argList.append(toJS(exec, arguments[i])); - JSObject* result = constructDate(exec, argList); + JSObject* result = constructDate(exec, exec->lexicalGlobalObject(), argList); if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); @@ -207,7 +207,7 @@ JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSV for (size_t i = 0; i < argumentCount; ++i) argList.append(toJS(exec, arguments[i])); - JSObject* result = constructRegExp(exec, argList); + JSObject* result = constructRegExp(exec, exec->lexicalGlobalObject(), argList); if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); diff --git a/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp b/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp index bc5e383..54dfda6 100644 --- a/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp +++ b/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp @@ -68,14 +68,11 @@ JSObjectRef JSWeakObjectMapGet(JSContextRef ctx, JSWeakObjectMapRef map, void* k return toRef(static_cast<JSObject*>(map->map().get(key))); } -bool JSWeakObjectMapClear(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSObjectRef object) +// We need to keep this function in the build to keep the nightlies running. +JS_EXPORT bool JSWeakObjectMapClear(JSContextRef, JSWeakObjectMapRef, void*, JSObjectRef); +bool JSWeakObjectMapClear(JSContextRef, JSWeakObjectMapRef, void*, JSObjectRef) { - ExecState* exec = toJS(ctx); - APIEntryShim entryShim(exec); - JSObject* obj = toJS(object); - if (map->map().deprecatedRemove(key, obj)) - return true; - return false; + return true; } #ifdef __cplusplus diff --git a/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.h b/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.h index bb3fe96..01e0611 100644 --- a/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.h +++ b/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.h @@ -76,17 +76,6 @@ JS_EXPORT void JSWeakObjectMapSet(JSContextRef ctx, JSWeakObjectMapRef map, void */ JS_EXPORT JSObjectRef JSWeakObjectMapGet(JSContextRef ctx, JSWeakObjectMapRef map, void* key); -/*! - @function - @abstract Clears the association between a key and an object in a JSWeakObjectMapRef - @param ctx The execution context to use. - @param map The map to clear the key association from. - @param key The key to use. - @param object The old object value. - @result Returns true if the key/object association was present in map, and has been removed. - */ -JS_EXPORT bool JSWeakObjectMapClear(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSObjectRef object); - #ifdef __cplusplus } #endif diff --git a/Source/JavaScriptCore/API/OpaqueJSString.h b/Source/JavaScriptCore/API/OpaqueJSString.h index 473c815..69c0962 100644 --- a/Source/JavaScriptCore/API/OpaqueJSString.h +++ b/Source/JavaScriptCore/API/OpaqueJSString.h @@ -33,7 +33,7 @@ namespace JSC { class JSGlobalData; } -struct OpaqueJSString : public ThreadSafeShared<OpaqueJSString> { +struct OpaqueJSString : public ThreadSafeRefCounted<OpaqueJSString> { static PassRefPtr<OpaqueJSString> create() // null { @@ -54,7 +54,7 @@ struct OpaqueJSString : public ThreadSafeShared<OpaqueJSString> { JSC::Identifier identifier(JSC::JSGlobalData*) const; private: - friend class WTF::ThreadSafeShared<OpaqueJSString>; + friend class WTF::ThreadSafeRefCounted<OpaqueJSString>; OpaqueJSString() : m_characters(0) diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt index 97f100e..247d372 100644 --- a/Source/JavaScriptCore/CMakeLists.txt +++ b/Source/JavaScriptCore/CMakeLists.txt @@ -42,6 +42,7 @@ SET(JavaScriptCore_SOURCES bytecompiler/NodesCodegen.cpp collector/handles/HandleHeap.cpp + collector/handles/HandleStack.cpp debugger/Debugger.cpp debugger/DebuggerActivation.cpp diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 162f23f..7cc1d15 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,3 +1,3318 @@ +2011-03-30 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + Make StructureChain GC allocated + https://bugs.webkit.org/show_bug.cgi?id=56695 + + Make StructureChain GC allocated, and make the various owners + mark it correctly. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + (JSC::CodeBlock::derefStructures): + (JSC::CodeBlock::refStructures): + (JSC::CodeBlock::markAggregate): + * bytecode/Instruction.h: + (JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::set): + (JSC::PolymorphicAccessStructureList::PolymorphicAccessStructureList): + (JSC::PolymorphicAccessStructureList::derefStructures): + (JSC::PolymorphicAccessStructureList::markAggregate): + (JSC::Instruction::Instruction): + * bytecode/StructureStubInfo.cpp: + (JSC::StructureStubInfo::deref): + (JSC::StructureStubInfo::markAggregate): + * bytecode/StructureStubInfo.h: + (JSC::StructureStubInfo::initGetByIdChain): + (JSC::StructureStubInfo::initPutByIdTransition): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitJumpIfNotFunctionCall): + (JSC::BytecodeGenerator::emitJumpIfNotFunctionApply): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_jneq_ptr): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::emit_op_jneq_ptr): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::privateCompileGetByIdChainList): + * jit/JITPropertyAccess32_64.cpp: + (JSC::JIT::privateCompileGetByIdChainList): + * jit/JITStubs.cpp: + (JSC::getPolymorphicAccessStructureListSlot): + (JSC::DEFINE_STUB_FUNCTION): + * runtime/JSCell.h: + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + * runtime/JSGlobalData.h: + * runtime/JSGlobalObject.cpp: + (JSC::markIfNeeded): + * runtime/JSGlobalObject.h: + (JSC::Structure::prototypeChain): + * runtime/JSObject.h: + (JSC::JSObject::markChildrenDirect): + * runtime/JSPropertyNameIterator.cpp: + (JSC::JSPropertyNameIterator::create): + (JSC::JSPropertyNameIterator::get): + (JSC::JSPropertyNameIterator::markChildren): + * runtime/JSPropertyNameIterator.h: + (JSC::JSPropertyNameIterator::setCachedPrototypeChain): + * runtime/MarkStack.h: + (JSC::MarkStack::append): + * runtime/Structure.h: + (JSC::Structure::cachedPrototypeChainSlot): + * runtime/StructureChain.cpp: + (JSC::StructureChain::StructureChain): + * runtime/StructureChain.h: + (JSC::StructureChain::create): + (JSC::StructureChain::createStructure): + +2011-03-30 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Adam Roben. + + Update Windows production build logic for new production configurations + https://bugs.webkit.org/show_bug.cgi?id=57494 + + * JavaScriptCore.vcproj/JavaScriptCore.make: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreProduction.vsprops: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGO.vsprops: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGOOptimize.vsprops: + * JavaScriptCore.vcproj/WTF/WTFProduction.vsprops: + * JavaScriptCore.vcproj/WTF/WTFReleasePGO.vsprops: + * JavaScriptCore.vcproj/jsc/jscProduction.vsprops: + * JavaScriptCore.vcproj/jsc/jscReleasePGO.vsprops: + * JavaScriptCore.vcproj/testapi/testapiProduction.vsprops: + +2011-03-30 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Adam Roben. + + Rename Windows configuration Release_LTCG to Production for clarity + https://bugs.webkit.org/show_bug.cgi?id=57465 + + * JavaScriptCore.vcproj/JavaScriptCore.sln: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreProduction.vsprops: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleaseLTCG.vsprops. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleaseLTCG.vsprops: Removed. + * JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.vcproj/WTF/WTFProduction.vsprops: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFReleaseLTCG.vsprops. + * JavaScriptCore.vcproj/WTF/WTFReleaseLTCG.vsprops: Removed. + * JavaScriptCore.vcproj/jsc/jsc.vcproj: + * JavaScriptCore.vcproj/jsc/jscProduction.vsprops: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscReleaseLTCG.vsprops. + * JavaScriptCore.vcproj/jsc/jscReleaseLTCG.vsprops: Removed. + * JavaScriptCore.vcproj/testapi/testapi.vcproj: + * JavaScriptCore.vcproj/testapi/testapiProduction.vsprops: Copied from Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiReleaseLTCG.vsprops. + * JavaScriptCore.vcproj/testapi/testapiReleaseLTCG.vsprops: Removed. + +2011-03-30 Zoltan Herczeg <zherczeg@inf.u-szeged.hu> + + Reviewed by Maciej Stachowiak. + + Add the NEXT_OPCODE() macro to the DFG-JIT parser + https://bugs.webkit.org/show_bug.cgi?id=57322 + + In JavaScriptCore we use macros to jump to the next opcode + (both in interpreter and JIT). This macro is added to the + DFG-JIT parser as well. + + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::parse): + +2011-03-29 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Darin Adler. + + ~25% regression on v8-splay in the SunSpider harness + https://bugs.webkit.org/show_bug.cgi?id=56128 + + I'm not sure if this is the root cause of the regression Stephanie + measured, but it seems to get us back to previous v8-splay times. + + SunSpider reports no change. v8-splay says 41% faster. + + * runtime/Heap.cpp: + (JSC::Heap::reset): Make marking proportional to 1X the size of the heap, + not .5X the size of the heap. When the heap is large, this makes a big + difference. (Our old heap growth policy matched this. You can see by + looking at resizeBlocks in revisions prior to r77699.) + +2011-03-29 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Darin Adler. + + Use per-configuration vsprops in JavaScriptCore to avoid WebKitVSPropsRedirectionDir removal by MSVC IDE + https://bugs.webkit.org/show_bug.cgi?id=57350 + + Visual Studio's IDE was removing instances of $(WebKitVSPropsRedirectionDir) from + InheritedPropertySheet rules in our vcproj files when the vcproj was edited from within + the IDE. To avoid this, add a separate vsprops file for each project configuration that + contains the required inherited property sheets. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreDebug.vsprops: Added. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreDebugAll.vsprops: Added. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreDebugCairoCFLite.vsprops: Added. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreRelease.vsprops: Added. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleaseCairoCFLite.vsprops: Added. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleaseLTCG.vsprops: Added. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGO.vsprops: Added. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGOOptimize.vsprops: Added. + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.vcproj/WTF/WTFDebug.vsprops: Added. + * JavaScriptCore.vcproj/WTF/WTFDebugAll.vsprops: Added. + * JavaScriptCore.vcproj/WTF/WTFDebugCairoCFLite.vsprops: Added. + * JavaScriptCore.vcproj/WTF/WTFRelease.vsprops: Added. + * JavaScriptCore.vcproj/WTF/WTFReleaseCairoCFLite.vsprops: Added. + * JavaScriptCore.vcproj/WTF/WTFReleaseLTCG.vsprops: Added. + * JavaScriptCore.vcproj/WTF/WTFReleasePGO.vsprops: Added. + * JavaScriptCore.vcproj/jsc/jsc.vcproj: + * JavaScriptCore.vcproj/jsc/jscDebug.vsprops: Added. + * JavaScriptCore.vcproj/jsc/jscDebugAll.vsprops: Added. + * JavaScriptCore.vcproj/jsc/jscDebugCairoCFLite.vsprops: Added. + * JavaScriptCore.vcproj/jsc/jscRelease.vsprops: Added. + * JavaScriptCore.vcproj/jsc/jscReleaseCairoCFLite.vsprops: Added. + * JavaScriptCore.vcproj/jsc/jscReleaseLTCG.vsprops: Added. + * JavaScriptCore.vcproj/jsc/jscReleasePGO.vsprops: Added. + * JavaScriptCore.vcproj/testapi/testapi.vcproj: + * JavaScriptCore.vcproj/testapi/testapiDebug.vsprops: Added. + * JavaScriptCore.vcproj/testapi/testapiDebugAll.vsprops: Added. + * JavaScriptCore.vcproj/testapi/testapiDebugCairoCFLite.vsprops: Added. + * JavaScriptCore.vcproj/testapi/testapiRelease.vsprops: Added. + * JavaScriptCore.vcproj/testapi/testapiReleaseCairoCFLite.vsprops: Added. + * JavaScriptCore.vcproj/testapi/testapiReleaseLTCG.vsprops: Added. + +2011-03-29 Oliver Hunt <oliver@apple.com> + + Reviewed by Eric Seidel. + + REGRESSION(r82173): Causes assertion and test failures in run-javascriptcore-tests on Windows (Requested by aroben on #webkit). + https://bugs.webkit.org/show_bug.cgi?id=57333 + + constructDate now takes the global object explicitly as it may be called + by functions other than the constructor itself. + + * API/JSObjectRef.cpp: + (JSObjectMakeDate): + * runtime/DateConstructor.cpp: + (JSC::constructDate): + (JSC::constructWithDateConstructor): + * runtime/DateConstructor.h: + +2011-03-29 Ben Taylor <bentaylor.solx86@gmail.com> + + Reviewed by Benjamin Poulain. + + https://bugs.webkit.org/show_bug.cgi?id=41953 + + Fix compile error on Solaris 10/Sun Studio 12 CC emanating from MathExtras.h + + * wtf/MathExtras.h: + +2011-03-29 Ben Taylor <bentaylor.solx86@gmail.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=57231 + Add conditional for SUNCC supporting alignment macros + + Compile fix for Solaris 10/Sun Studio 12 CC + + * wtf/Vector.h: + +2011-03-29 Ben Taylor <bentaylor.solx86@gmail.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=57256 + + Fix crash on misaligned reads on Solaris 10/Sparc + + * wtf/text/AtomicString.cpp: + (WTF::equal): + +2011-03-28 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + instanceof Array test fails when using iframes + https://bugs.webkit.org/show_bug.cgi?id=17250 + + This is a problem with all built in constructors, the use of + lexicalGlobalObject rather than the constructors own + global object reference means that a builtin will always use + the prototype from the lexical global object rather than that + of the constructors origin. + + * API/JSObjectRef.cpp: + (JSObjectMakeFunction): + (JSObjectMakeRegExp): + * JavaScriptCore.exp: + * runtime/ArrayConstructor.cpp: + (JSC::constructArrayWithSizeQuirk): + * runtime/BooleanConstructor.cpp: + (JSC::constructBoolean): + (JSC::constructBooleanFromImmediateBoolean): + * runtime/BooleanConstructor.h: + * runtime/DateConstructor.cpp: + (JSC::constructDate): + * runtime/DateInstance.cpp: + * runtime/DateInstance.h: + * runtime/ErrorConstructor.cpp: + (JSC::constructWithErrorConstructor): + (JSC::callErrorConstructor): + * runtime/FunctionConstructor.cpp: + (JSC::constructWithFunctionConstructor): + (JSC::callFunctionConstructor): + (JSC::constructFunction): + * runtime/FunctionConstructor.h: + * runtime/JSCell.cpp: + (JSC::JSCell::getOwnPropertySlot): + (JSC::JSCell::put): + (JSC::JSCell::deleteProperty): + (JSC::JSCell::toThisObject): + (JSC::JSCell::toObject): + * runtime/JSCell.h: + (JSC::JSCell::JSValue::toObject): + * runtime/JSNotAnObject.cpp: + (JSC::JSNotAnObject::toObject): + * runtime/JSNotAnObject.h: + * runtime/JSObject.cpp: + (JSC::JSObject::toObject): + * runtime/JSObject.h: + * runtime/JSString.cpp: + (JSC::StringObject::create): + (JSC::JSString::toObject): + (JSC::JSString::toThisObject): + * runtime/JSString.h: + * runtime/JSValue.cpp: + (JSC::JSValue::toObjectSlowCase): + (JSC::JSValue::toThisObjectSlowCase): + (JSC::JSValue::synthesizeObject): + * runtime/JSValue.h: + * runtime/NumberConstructor.cpp: + (JSC::constructWithNumberConstructor): + * runtime/NumberObject.cpp: + (JSC::constructNumber): + * runtime/NumberObject.h: + * runtime/ObjectConstructor.cpp: + (JSC::constructObject): + (JSC::constructWithObjectConstructor): + (JSC::callObjectConstructor): + * runtime/RegExpConstructor.cpp: + (JSC::constructRegExp): + (JSC::constructWithRegExpConstructor): + (JSC::callRegExpConstructor): + * runtime/RegExpConstructor.h: + * runtime/StringConstructor.cpp: + (JSC::constructWithStringConstructor): + * runtime/StringObject.h: + +2011-03-28 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + REGRESSION [r78794-r79249] Allocation of memory is slow when number of active objects is large + https://bugs.webkit.org/show_bug.cgi?id=56823 + + Partial fix for most of the problem. (TOT still shows a regression, though.) + + * runtime/Heap.cpp: + (JSC::Heap::reportExtraMemoryCostSlowCase): Use highWaterMark(), instead of + capacity(), since capacity() is O(n) relative to the size of the heap. + + In limited circumstances, capacity() is also worse than highWaterMark() + for measuring extra cost relative to heap size, since capacity() only + measures the *current* capacity of the heap, but the heap will grow if + necessary to attain highWaterMark(). + +2011-03-28 Oliver Hunt <oliver@apple.com> + + REGRESSION(r82130): It made all tests crash (Requested by Ossy on #webkit). + https://bugs.webkit.org/show_bug.cgi?id=57251 + + Build fix, had remnant of another patch in r82130 + + * jit/JITPropertyAccess.cpp: + (JSC::JIT::privateCompileGetByIdChainList): + +2011-03-27 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + Add additional immediate types to allow us to distinguish the source of a JIT immediate + https://bugs.webkit.org/show_bug.cgi?id=57190 + + Allow us to distinguish whether a JIT immediate is a value that we + control (TrustedImm32 and TrustedImmPtr) vs. ones that can be controlled + or influenced by code we are compiling. Currently we do nothing with this + information -- this change is large and mechanical but would obscure any + logic changes that we would have made. + + * assembler/AbstractMacroAssembler.h: + (JSC::AbstractMacroAssembler::TrustedImmPtr::TrustedImmPtr): + (JSC::AbstractMacroAssembler::ImmPtr::ImmPtr): + (JSC::AbstractMacroAssembler::TrustedImm32::TrustedImm32): + (JSC::AbstractMacroAssembler::Imm32::Imm32): + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::pop): + (JSC::MacroAssembler::poke): + (JSC::MacroAssembler::branchPtr): + (JSC::MacroAssembler::branch32): + (JSC::MacroAssembler::addPtr): + (JSC::MacroAssembler::andPtr): + (JSC::MacroAssembler::orPtr): + (JSC::MacroAssembler::subPtr): + (JSC::MacroAssembler::xorPtr): + (JSC::MacroAssembler::setPtr): + (JSC::MacroAssembler::storePtr): + (JSC::MacroAssembler::branchTestPtr): + (JSC::MacroAssembler::branchSubPtr): + (JSC::MacroAssembler::branchTest8): + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::add32): + (JSC::MacroAssemblerARM::and32): + (JSC::MacroAssemblerARM::lshift32): + (JSC::MacroAssemblerARM::mul32): + (JSC::MacroAssemblerARM::or32): + (JSC::MacroAssemblerARM::rshift32): + (JSC::MacroAssemblerARM::urshift32): + (JSC::MacroAssemblerARM::sub32): + (JSC::MacroAssemblerARM::xor32): + (JSC::MacroAssemblerARM::store32): + (JSC::MacroAssemblerARM::push): + (JSC::MacroAssemblerARM::move): + (JSC::MacroAssemblerARM::branch8): + (JSC::MacroAssemblerARM::branch32): + (JSC::MacroAssemblerARM::branch32WithUnalignedHalfWords): + (JSC::MacroAssemblerARM::branch16): + (JSC::MacroAssemblerARM::branchTest8): + (JSC::MacroAssemblerARM::branchTest32): + (JSC::MacroAssemblerARM::branchAdd32): + (JSC::MacroAssemblerARM::branchMul32): + (JSC::MacroAssemblerARM::branchSub32): + (JSC::MacroAssemblerARM::set32Compare32): + (JSC::MacroAssemblerARM::set8Compare32): + (JSC::MacroAssemblerARM::set32Test32): + (JSC::MacroAssemblerARM::set32Test8): + (JSC::MacroAssemblerARM::moveWithPatch): + (JSC::MacroAssemblerARM::branchPtrWithPatch): + (JSC::MacroAssemblerARM::storePtrWithPatch): + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::add32): + (JSC::MacroAssemblerARMv7::and32): + (JSC::MacroAssemblerARMv7::lshift32): + (JSC::MacroAssemblerARMv7::mul32): + (JSC::MacroAssemblerARMv7::or32): + (JSC::MacroAssemblerARMv7::rshift32): + (JSC::MacroAssemblerARMv7::urshift32): + (JSC::MacroAssemblerARMv7::sub32): + (JSC::MacroAssemblerARMv7::xor32): + (JSC::MacroAssemblerARMv7::load32): + (JSC::MacroAssemblerARMv7::load32WithAddressOffsetPatch): + (JSC::MacroAssemblerARMv7::load16): + (JSC::MacroAssemblerARMv7::store32WithAddressOffsetPatch): + (JSC::MacroAssemblerARMv7::store32): + (JSC::MacroAssemblerARMv7::loadDouble): + (JSC::MacroAssemblerARMv7::storeDouble): + (JSC::MacroAssemblerARMv7::push): + (JSC::MacroAssemblerARMv7::move): + (JSC::MacroAssemblerARMv7::compare32): + (JSC::MacroAssemblerARMv7::test32): + (JSC::MacroAssemblerARMv7::branch32): + (JSC::MacroAssemblerARMv7::branch32WithUnalignedHalfWords): + (JSC::MacroAssemblerARMv7::branch16): + (JSC::MacroAssemblerARMv7::branch8): + (JSC::MacroAssemblerARMv7::branchTest32): + (JSC::MacroAssemblerARMv7::branchTest8): + (JSC::MacroAssemblerARMv7::branchAdd32): + (JSC::MacroAssemblerARMv7::branchMul32): + (JSC::MacroAssemblerARMv7::branchSub32): + (JSC::MacroAssemblerARMv7::nearCall): + (JSC::MacroAssemblerARMv7::call): + (JSC::MacroAssemblerARMv7::set32Compare32): + (JSC::MacroAssemblerARMv7::set8Compare32): + (JSC::MacroAssemblerARMv7::set32Test32): + (JSC::MacroAssemblerARMv7::set32Test8): + (JSC::MacroAssemblerARMv7::moveWithPatch): + (JSC::MacroAssemblerARMv7::branchPtrWithPatch): + (JSC::MacroAssemblerARMv7::storePtrWithPatch): + (JSC::MacroAssemblerARMv7::tailRecursiveCall): + (JSC::MacroAssemblerARMv7::makeJump): + (JSC::MacroAssemblerARMv7::makeBranch): + (JSC::MacroAssemblerARMv7::setupArmAddress): + (JSC::MacroAssemblerARMv7::makeBaseIndexBase): + (JSC::MacroAssemblerARMv7::moveFixedWidthEncoding): + * assembler/MacroAssemblerMIPS.h: + (JSC::MacroAssemblerMIPS::add32): + (JSC::MacroAssemblerMIPS::and32): + (JSC::MacroAssemblerMIPS::lshift32): + (JSC::MacroAssemblerMIPS::mul32): + (JSC::MacroAssemblerMIPS::or32): + (JSC::MacroAssemblerMIPS::rshift32): + (JSC::MacroAssemblerMIPS::urshift32): + (JSC::MacroAssemblerMIPS::sub32): + (JSC::MacroAssemblerMIPS::xor32): + (JSC::MacroAssemblerMIPS::load32): + (JSC::MacroAssemblerMIPS::load32WithAddressOffsetPatch): + (JSC::MacroAssemblerMIPS::store32WithAddressOffsetPatch): + (JSC::MacroAssemblerMIPS::store32): + (JSC::MacroAssemblerMIPS::push): + (JSC::MacroAssemblerMIPS::move): + (JSC::MacroAssemblerMIPS::branch8): + (JSC::MacroAssemblerMIPS::branch32): + (JSC::MacroAssemblerMIPS::branch32WithUnalignedHalfWords): + (JSC::MacroAssemblerMIPS::branch16): + (JSC::MacroAssemblerMIPS::branchTest32): + (JSC::MacroAssemblerMIPS::branchTest8): + (JSC::MacroAssemblerMIPS::branchAdd32): + (JSC::MacroAssemblerMIPS::branchMul32): + (JSC::MacroAssemblerMIPS::branchSub32): + (JSC::MacroAssemblerMIPS::set8Compare32): + (JSC::MacroAssemblerMIPS::set32Compare32): + (JSC::MacroAssemblerMIPS::set32Test8): + (JSC::MacroAssemblerMIPS::set32Test32): + (JSC::MacroAssemblerMIPS::moveWithPatch): + (JSC::MacroAssemblerMIPS::branchPtrWithPatch): + (JSC::MacroAssemblerMIPS::storePtrWithPatch): + (JSC::MacroAssemblerMIPS::tailRecursiveCall): + (JSC::MacroAssemblerMIPS::loadDouble): + (JSC::MacroAssemblerMIPS::storeDouble): + (JSC::MacroAssemblerMIPS::branchTruncateDoubleToInt32): + * assembler/MacroAssemblerX86.h: + (JSC::MacroAssemblerX86::add32): + (JSC::MacroAssemblerX86::addWithCarry32): + (JSC::MacroAssemblerX86::and32): + (JSC::MacroAssemblerX86::or32): + (JSC::MacroAssemblerX86::sub32): + (JSC::MacroAssemblerX86::store32): + (JSC::MacroAssemblerX86::branch32): + (JSC::MacroAssemblerX86::moveWithPatch): + (JSC::MacroAssemblerX86::branchPtrWithPatch): + (JSC::MacroAssemblerX86::storePtrWithPatch): + * assembler/MacroAssemblerX86Common.h: + (JSC::MacroAssemblerX86Common::add32): + (JSC::MacroAssemblerX86Common::and32): + (JSC::MacroAssemblerX86Common::lshift32): + (JSC::MacroAssemblerX86Common::mul32): + (JSC::MacroAssemblerX86Common::or32): + (JSC::MacroAssemblerX86Common::rshift32): + (JSC::MacroAssemblerX86Common::urshift32): + (JSC::MacroAssemblerX86Common::sub32): + (JSC::MacroAssemblerX86Common::xor32): + (JSC::MacroAssemblerX86Common::store32): + (JSC::MacroAssemblerX86Common::branchTruncateDoubleToInt32): + (JSC::MacroAssemblerX86Common::push): + (JSC::MacroAssemblerX86Common::move): + (JSC::MacroAssemblerX86Common::branch8): + (JSC::MacroAssemblerX86Common::branch32): + (JSC::MacroAssemblerX86Common::branch32WithUnalignedHalfWords): + (JSC::MacroAssemblerX86Common::branch16): + (JSC::MacroAssemblerX86Common::branchTest32): + (JSC::MacroAssemblerX86Common::branchTest8): + (JSC::MacroAssemblerX86Common::branchAdd32): + (JSC::MacroAssemblerX86Common::branchMul32): + (JSC::MacroAssemblerX86Common::branchSub32): + (JSC::MacroAssemblerX86Common::set8Compare32): + (JSC::MacroAssemblerX86Common::set32Compare32): + (JSC::MacroAssemblerX86Common::set32Test8): + (JSC::MacroAssemblerX86Common::set32Test32): + * assembler/MacroAssemblerX86_64.h: + (JSC::MacroAssemblerX86_64::add32): + (JSC::MacroAssemblerX86_64::and32): + (JSC::MacroAssemblerX86_64::or32): + (JSC::MacroAssemblerX86_64::sub32): + (JSC::MacroAssemblerX86_64::loadDouble): + (JSC::MacroAssemblerX86_64::addDouble): + (JSC::MacroAssemblerX86_64::convertInt32ToDouble): + (JSC::MacroAssemblerX86_64::store32): + (JSC::MacroAssemblerX86_64::call): + (JSC::MacroAssemblerX86_64::tailRecursiveCall): + (JSC::MacroAssemblerX86_64::makeTailRecursiveCall): + (JSC::MacroAssemblerX86_64::addPtr): + (JSC::MacroAssemblerX86_64::andPtr): + (JSC::MacroAssemblerX86_64::orPtr): + (JSC::MacroAssemblerX86_64::subPtr): + (JSC::MacroAssemblerX86_64::xorPtr): + (JSC::MacroAssemblerX86_64::storePtr): + (JSC::MacroAssemblerX86_64::setPtr): + (JSC::MacroAssemblerX86_64::branchPtr): + (JSC::MacroAssemblerX86_64::branchTestPtr): + (JSC::MacroAssemblerX86_64::branchSubPtr): + (JSC::MacroAssemblerX86_64::moveWithPatch): + (JSC::MacroAssemblerX86_64::branchPtrWithPatch): + (JSC::MacroAssemblerX86_64::storePtrWithPatch): + (JSC::MacroAssemblerX86_64::branchTest8): + * dfg/DFGJITCodeGenerator.h: + (JSC::DFG::JITCodeGenerator::callOperation): + * dfg/DFGJITCompiler.cpp: + (JSC::DFG::JITCompiler::jitAssertIsInt32): + (JSC::DFG::JITCompiler::emitCount): + * dfg/DFGJITCompiler.h: + (JSC::DFG::JITCompiler::emitPutImmediateToCallFrameHeader): + * dfg/DFGNonSpeculativeJIT.cpp: + (JSC::DFG::NonSpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::fillSpeculateCell): + (JSC::DFG::SpeculativeJIT::compile): + * jit/JIT.cpp: + (JSC::JIT::emitTimeoutCheck): + (JSC::JIT::privateCompile): + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::emit_op_urshift): + (JSC::JIT::emitSlow_op_urshift): + (JSC::JIT::emit_op_post_inc): + (JSC::JIT::emit_op_post_dec): + (JSC::JIT::emit_op_pre_inc): + (JSC::JIT::emit_op_pre_dec): + (JSC::JIT::emit_op_mod): + * jit/JITArithmetic32_64.cpp: + (JSC::JIT::emit_op_negate): + (JSC::JIT::emit_op_jnless): + (JSC::JIT::emit_op_jless): + (JSC::JIT::emit_op_jlesseq): + (JSC::JIT::emit_op_lshift): + (JSC::JIT::emitRightShift): + (JSC::JIT::emitRightShiftSlowCase): + (JSC::JIT::emit_op_bitand): + (JSC::JIT::emit_op_bitor): + (JSC::JIT::emit_op_bitxor): + (JSC::JIT::emit_op_bitnot): + (JSC::JIT::emit_op_post_inc): + (JSC::JIT::emit_op_post_dec): + (JSC::JIT::emitSlow_op_post_dec): + (JSC::JIT::emit_op_pre_inc): + (JSC::JIT::emit_op_pre_dec): + (JSC::JIT::emit_op_add): + (JSC::JIT::emitAdd32Constant): + (JSC::JIT::emit_op_sub): + (JSC::JIT::emitSub32Constant): + (JSC::JIT::emitBinaryDoubleOp): + (JSC::JIT::emit_op_mul): + (JSC::JIT::emitSlow_op_mul): + (JSC::JIT::emit_op_div): + (JSC::JIT::emit_op_mod): + * jit/JITCall.cpp: + (JSC::JIT::compileOpCallVarargs): + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpCallSlowCase): + * jit/JITCall32_64.cpp: + (JSC::JIT::compileOpCallVarargs): + (JSC::JIT::emit_op_ret_object_or_this): + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpCallSlowCase): + * jit/JITInlineMethods.h: + (JSC::JIT::emitPutCellToCallFrameHeader): + (JSC::JIT::emitPutIntToCallFrameHeader): + (JSC::JIT::emitPutImmediateToCallFrameHeader): + (JSC::JIT::emitLoadCharacterString): + (JSC::JIT::restoreArgumentReferenceForTrampoline): + (JSC::JIT::checkStructure): + (JSC::JIT::setSamplingFlag): + (JSC::JIT::clearSamplingFlag): + (JSC::JIT::emitCount): + (JSC::JIT::sampleInstruction): + (JSC::JIT::sampleCodeBlock): + (JSC::JIT::emitStoreInt32): + (JSC::JIT::emitStoreCell): + (JSC::JIT::emitStoreBool): + (JSC::JIT::emitJumpSlowCaseIfNotJSCell): + (JSC::JIT::emitInitRegister): + (JSC::JIT::emitJumpIfJSCell): + (JSC::JIT::emitJumpIfNotJSCell): + (JSC::JIT::emitJumpIfImmediateInteger): + (JSC::JIT::emitJumpIfNotImmediateInteger): + (JSC::JIT::emitFastArithDeTagImmediate): + (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero): + (JSC::JIT::emitFastArithReTagImmediate): + (JSC::JIT::emitTagAsBoolImmediate): + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + (JSC::JIT::privateCompileCTINativeCall): + (JSC::JIT::emit_op_check_has_instance): + (JSC::JIT::emit_op_instanceof): + (JSC::JIT::emit_op_ret_object_or_this): + (JSC::JIT::emit_op_resolve): + (JSC::JIT::emit_op_to_primitive): + (JSC::JIT::emit_op_resolve_base): + (JSC::JIT::emit_op_ensure_property_exists): + (JSC::JIT::emit_op_resolve_skip): + (JSC::JIT::emit_op_resolve_global): + (JSC::JIT::emitSlow_op_resolve_global): + (JSC::JIT::emit_op_not): + (JSC::JIT::emit_op_jfalse): + (JSC::JIT::emit_op_jeq_null): + (JSC::JIT::emit_op_jneq_null): + (JSC::JIT::emit_op_jneq_ptr): + (JSC::JIT::emit_op_jsr): + (JSC::JIT::emit_op_resolve_with_base): + (JSC::JIT::emit_op_new_func_exp): + (JSC::JIT::emit_op_jtrue): + (JSC::JIT::emit_op_get_pnames): + (JSC::JIT::emit_op_next_pname): + (JSC::JIT::emit_op_to_jsnumber): + (JSC::JIT::emit_op_push_new_scope): + (JSC::JIT::emit_op_catch): + (JSC::JIT::emit_op_eq_null): + (JSC::JIT::emit_op_neq_null): + (JSC::JIT::emit_op_init_lazy_reg): + (JSC::JIT::emit_op_convert_this): + (JSC::JIT::emit_op_convert_this_strict): + (JSC::JIT::emitSlow_op_not): + (JSC::JIT::emitSlow_op_neq): + (JSC::JIT::emit_op_get_arguments_length): + (JSC::JIT::emitSlow_op_get_arguments_length): + (JSC::JIT::emit_op_get_argument_by_val): + (JSC::JIT::emitSlow_op_resolve_global_dynamic): + (JSC::JIT::emit_op_new_regexp): + (JSC::JIT::emit_op_load_varargs): + (JSC::JIT::emitSlow_op_load_varargs): + (JSC::JIT::emit_op_new_func): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + (JSC::JIT::privateCompileCTINativeCall): + (JSC::JIT::emit_op_loop_if_lesseq): + (JSC::JIT::emit_op_check_has_instance): + (JSC::JIT::emit_op_instanceof): + (JSC::JIT::emit_op_get_scoped_var): + (JSC::JIT::emit_op_put_scoped_var): + (JSC::JIT::emit_op_tear_off_activation): + (JSC::JIT::emit_op_tear_off_arguments): + (JSC::JIT::emit_op_resolve): + (JSC::JIT::emit_op_to_primitive): + (JSC::JIT::emit_op_resolve_base): + (JSC::JIT::emit_op_ensure_property_exists): + (JSC::JIT::emit_op_resolve_skip): + (JSC::JIT::emit_op_resolve_global): + (JSC::JIT::emitSlow_op_resolve_global): + (JSC::JIT::emit_op_not): + (JSC::JIT::emit_op_jfalse): + (JSC::JIT::emit_op_jtrue): + (JSC::JIT::emit_op_jeq_null): + (JSC::JIT::emit_op_jneq_null): + (JSC::JIT::emit_op_jneq_ptr): + (JSC::JIT::emit_op_jsr): + (JSC::JIT::emit_op_eq): + (JSC::JIT::emitSlow_op_eq): + (JSC::JIT::emit_op_neq): + (JSC::JIT::emitSlow_op_neq): + (JSC::JIT::compileOpStrictEq): + (JSC::JIT::emit_op_eq_null): + (JSC::JIT::emit_op_neq_null): + (JSC::JIT::emit_op_resolve_with_base): + (JSC::JIT::emit_op_new_func_exp): + (JSC::JIT::emit_op_get_pnames): + (JSC::JIT::emit_op_next_pname): + (JSC::JIT::emit_op_to_jsnumber): + (JSC::JIT::emit_op_push_new_scope): + (JSC::JIT::emit_op_catch): + (JSC::JIT::emit_op_create_activation): + (JSC::JIT::emit_op_create_arguments): + (JSC::JIT::emit_op_convert_this): + (JSC::JIT::emit_op_convert_this_strict): + (JSC::JIT::emit_op_get_arguments_length): + (JSC::JIT::emitSlow_op_get_arguments_length): + (JSC::JIT::emit_op_get_argument_by_val): + (JSC::JIT::softModulo): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::stringGetByValStubGenerator): + (JSC::JIT::emit_op_get_by_val): + (JSC::JIT::emitSlow_op_get_by_val): + (JSC::JIT::emit_op_get_by_pname): + (JSC::JIT::emit_op_put_by_val): + (JSC::JIT::emit_op_put_by_index): + (JSC::JIT::emit_op_put_getter): + (JSC::JIT::emit_op_put_setter): + (JSC::JIT::emit_op_del_by_id): + (JSC::JIT::emit_op_get_by_id): + (JSC::JIT::emit_op_put_by_id): + (JSC::JIT::emit_op_method_check): + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compileGetByIdSlowCase): + (JSC::JIT::emitSlow_op_put_by_id): + (JSC::JIT::testPrototype): + (JSC::JIT::privateCompilePutByIdTransition): + (JSC::JIT::privateCompilePatchGetArrayLength): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + * jit/JITPropertyAccess32_64.cpp: + (JSC::JIT::emit_op_put_getter): + (JSC::JIT::emit_op_put_setter): + (JSC::JIT::emit_op_del_by_id): + (JSC::JIT::emit_op_get_by_id): + (JSC::JIT::emit_op_put_by_id): + (JSC::JIT::emit_op_method_check): + (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::compileGetByIdHotPath): + (JSC::JIT::compileGetByIdSlowCase): + (JSC::JIT::emitSlow_op_put_by_id): + (JSC::JIT::testPrototype): + (JSC::JIT::privateCompilePutByIdTransition): + (JSC::JIT::privateCompilePatchGetArrayLength): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + (JSC::JIT::emit_op_get_by_pname): + * jit/JITStubCall.h: + (JSC::JITStubCall::addArgument): + * jit/JITStubs.cpp: + (JSC::getPolymorphicAccessStructureListSlot): + (JSC::DEFINE_STUB_FUNCTION): + * jit/JSInterfaceJIT.h: + (JSC::JSInterfaceJIT::emitJumpIfNotJSCell): + (JSC::JSInterfaceJIT::emitLoadInt32): + (JSC::JSInterfaceJIT::emitLoadDouble): + * jit/SpecializedThunkJIT.h: + (JSC::SpecializedThunkJIT::SpecializedThunkJIT): + (JSC::SpecializedThunkJIT::loadJSStringArgument): + (JSC::SpecializedThunkJIT::tagReturnAsInt32): + (JSC::SpecializedThunkJIT::tagReturnAsJSCell): + * jit/ThunkGenerators.cpp: + (JSC::charToString): + (JSC::powThunkGenerator): + * yarr/YarrJIT.cpp: + (JSC::Yarr::YarrGenerator::matchCharacterClass): + (JSC::Yarr::YarrGenerator::storeToFrame): + (JSC::Yarr::YarrGenerator::storeToFrameWithPatch): + (JSC::Yarr::YarrGenerator::ParenthesesTail::generateCode): + (JSC::Yarr::YarrGenerator::generatePatternCharacterSingle): + (JSC::Yarr::YarrGenerator::generatePatternCharacterFixed): + (JSC::Yarr::YarrGenerator::generatePatternCharacterGreedy): + (JSC::Yarr::YarrGenerator::generatePatternCharacterNonGreedy): + (JSC::Yarr::YarrGenerator::generateCharacterClassFixed): + (JSC::Yarr::YarrGenerator::generateCharacterClassGreedy): + (JSC::Yarr::YarrGenerator::generateCharacterClassNonGreedy): + (JSC::Yarr::YarrGenerator::generateParenthesesSingle): + (JSC::Yarr::YarrGenerator::generateDisjunction): + +2011-03-28 Andras Becsi <abecsi@webkit.org> + + Reviewed by Csaba Osztrogonác. + + [Qt] Fix the linking of jsc with MinGW after r81963. + + * jsc.pro: add -l and remove the lib suffix. + +2011-03-27 Ben Taylor <bentaylor.solx86@gmail.com> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=57170 Fix last elements + in an enum to remove a trailing comma. Sun Studio 12 CC errors out. + + Compile fix only, no actual code change. + + * wtf/MessageQueue.h: + +2011-03-25 Oliver Hunt <oliver@apple.com> + + Reviewed by Darin Adler. + + Allow defineOwnProperty to work on DOMObjects + https://bugs.webkit.org/show_bug.cgi?id=57129 + + Fix a couple of places where we uses getter()/setter() rather + than [gs]etterPresent(). + + * runtime/JSObject.cpp: + (JSC::JSObject::defineOwnProperty): + +2011-03-25 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Crash when paused at a breakpoint caused by inaccurate Activation records. + https://bugs.webkit.org/show_bug.cgi?id=57120 + + * runtime/JSActivation.cpp: + (JSC::JSActivation::symbolTableGet): + (JSC::JSActivation::symbolTablePut): + (JSC::JSActivation::getOwnPropertyNames): + (JSC::JSActivation::symbolTablePutWithAttributes): + +2011-03-24 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Crash in debugger beneath MarkStack::drain @ me.com, ibm.com + https://bugs.webkit.org/show_bug.cgi?id=57080 + <rdar://problem/8525907> + + The crash was caused by changes in the executable after recompilation. + + The fix is for the activation to copy the data it needs instead of + relying on the data in the executable. + + SunSpider and v8 report no change. + + * runtime/Arguments.h: + (JSC::JSActivation::copyRegisters): Use our own data members instead of + reading data out of the executable. + + * runtime/JSActivation.cpp: + (JSC::JSActivation::JSActivation): Initialize our data members. + + (JSC::JSActivation::markChildren): + (JSC::JSActivation::symbolTableGet): + (JSC::JSActivation::symbolTablePut): + (JSC::JSActivation::getOwnPropertyNames): + (JSC::JSActivation::symbolTablePutWithAttributes): + (JSC::JSActivation::isDynamicScope): + (JSC::JSActivation::argumentsGetter): Use our own data members instead of + reading data out of the executable. + + * runtime/JSActivation.h: Added new data members to track data previously + tracked by the executable. Since I've removed the executable pointer, + on a 64bit system, I've only made activations bigger by an int. + +2011-03-25 David Kilzer <ddkilzer@apple.com> + + Remove duplicate entry from JavaScriptCore.exp + + JSC::createStackOverflowError(JSC::ExecState*) was originally + exported in r60057, then duplicated in r60392. + + * JavaScriptCore.exp: Removed duplicate entry. + +2011-03-25 Jarred Nicholls <jarred@sencha.com> + + Reviewed by Ariya Hidayat. + + [Qt] MSVC Build Error - need to link advapi32.lib for jsc.exe + https://bugs.webkit.org/show_bug.cgi?id=56098 + + Need to link advapi32.lib for jsc.exe since wtf/OSRandomSource.cpp uses the Win32 Crypto API + + * jsc.pro: + +2011-03-24 Nikolas Zimmermann <nzimmermann@rim.com> + + Reviewed by Darin Adler. + + Introduce WTF HexNumber.h + https://bugs.webkit.org/show_bug.cgi?id=56099 + + Introduce a set of functions that ease converting from a bye or a number to a hex string, + replacing several of these conversions and String::format("%x") usages all over WebCore. + + * GNUmakefile.am: Add HexNumber.h to build. + * JavaScriptCore.exp: Export StringBuilder::reserveCapacity. + * JavaScriptCore.gypi: Add HexNumber.h to build. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Export StringBuilder::reserveCapacity. + * JavaScriptCore.vcproj/WTF/WTF.vcproj: Add HexNumber.h to build. + * JavaScriptCore.xcodeproj/project.pbxproj: Ditto. + * wtf/CMakeLists.txt: Ditto. + * wtf/HexNumber.h: Added. + (WTF::Internal::hexDigitsForMode): Internal helper. + (WTF::appendByteAsHex): Free function, that appends a byte as hex string into a destination. + (WTF::placeByteAsHex): Ditto, but places the result using *foo++ = '..' or foo[index++] = '..' + (WTF::appendUnsignedAsHex): Free function, that appends a number as hex string into a destination. + +2011-03-24 Geoffrey Garen <ggaren@apple.com> + + Windows build fix take 2: Add new symobl. + + (I should have used the EWS bots for this!) + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2011-03-24 Geoffrey Garen <ggaren@apple.com> + + Windows build fix take 1: Removed old symobl. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2011-03-24 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Ensure that all compilation takes place within a dynamic global object scope + https://bugs.webkit.org/show_bug.cgi?id=57054 + <rdar://problem/9083011> + + Otherwise, entry to the global object scope might throw away the code + we just compiled, causing a crash. + + * JavaScriptCore.exp: Updated for signature change. + + * debugger/Debugger.cpp: + (JSC::evaluateInGlobalCallFrame): + * debugger/DebuggerCallFrame.cpp: + (JSC::DebuggerCallFrame::evaluate): Removed explicit compilation calls + here because (a) they took place outside a dynamic global object scope + and (b) they were redundant. + + * interpreter/CachedCall.h: + (JSC::CachedCall::CachedCall): Updated for signature change. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::execute): + (JSC::Interpreter::executeCall): + (JSC::Interpreter::executeConstruct): Declare our dynamic global object + scope earlier, to ensure that compilation takes place within it. + + * runtime/Completion.cpp: + (JSC::evaluate): Removed explicit compilation calls here because (a) + they took place outside a dynamic global object scope and (b) they were + redundant. + + * runtime/Executable.h: + (JSC::EvalExecutable::compile): + (JSC::ProgramExecutable::compile): + (JSC::FunctionExecutable::compileForCall): + (JSC::FunctionExecutable::compileForConstruct): Added an ASSERT to + verify our new invariant that all compilation takes place within a + dynamic global object scope. + + * runtime/JSGlobalObject.cpp: + (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): + * runtime/JSGlobalObject.h: Changed the signature of DynamicGlobalObjectScope + to require a JSGlobalData instead of an ExecState* since it is often + easier to provide the former, and the latter was not necessary. + +2011-03-24 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + REGRESSION (r79987-r80210): Crash in JSWeakObjectMapClear + https://bugs.webkit.org/show_bug.cgi?id=55671 + + This is no longer necessary, and it seems that with the new weakmap + model it's simply unsafe, so this reduces it to a no-op. + + * API/JSWeakObjectMapRefPrivate.cpp: + +2011-03-24 Ben Taylor <bentaylor.solx86@gmail.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=20302 + Correct implementation of signbit on Solaris + + * wtf/MathExtras.h: + (signbit): + +2011-03-23 Mark Rowe <mrowe@apple.com> + + Reviewed by Darin Adler. + + <rdar://problem/7959320> Threads that use APIs above the BSD layer must be registered with the Obj-C GC. + + * wtf/ThreadingPthreads.cpp: + (WTF::initializeCurrentThreadInternal): + +2011-03-23 Mark Rowe <mrowe@apple.com> + + Stop setting OTHER_OPTIONS in JavaScriptCore's Makefile. + + It's not necessary to pass "-target All" as xcodebuild always builds the + first target in the project unless otherwise specified. The presence of + that option also breaks "make clean" since that results in both the + -target and -alltargets options being passed to xcodebuild. + + * Makefile: + +2011-03-23 Pavel Feldman <pfeldman@chromium.org> + + Not reviewed: bring back Vector::contains that was removed as a part of roll back. + + * wtf/Vector.h: + (WTF::::contains): + +2011-03-23 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r81686. + http://trac.webkit.org/changeset/81686 + https://bugs.webkit.org/show_bug.cgi?id=56914 + + Breaks webkit_tests in Chromium again. (Requested by pfeldman + on #webkit). + + * wtf/Vector.h: + +2011-03-23 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + JavaScriptCore GYP build should work on a case-sensitive file system + https://bugs.webkit.org/show_bug.cgi?id=56911 + + The issue is that there are two UString.h headers, one named UString.h + and one named ustring.h. This patch excludes ustring.h from the header + map to avoid confusion. While I was editing this part of the GYP file, + I cleaned up the exclude rules to be more modern. + + * gyp/JavaScriptCore.gyp: + +2011-03-22 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Maciej Stachowiak. + + REGRESSION (r78382): No scripts appear in the Web Inspector's Scripts + panel on Windows, and many inspector regression tests are failing + https://bugs.webkit.org/show_bug.cgi?id=54490 + + The bug was caused by two different classes using the same name (Recompiler). + + * debugger/Debugger.cpp: + * runtime/JSGlobalData.cpp: + (WTF::Recompiler::operator()): Put Recompiler in an anonymous namespace, + so our two recompilers' inline functions don't stomp each other at + link time. + +2011-03-22 Sam Weinig <sam@webkit.org> + + Reviewed by Mark Rowe. + + Remove USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER. + <rdar://problem/8944718> + + * DerivedSources.make: + Remove generation of USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER. + +2011-03-22 Gabor Loki <loki@webkit.org> + + Reviewed by Csaba Osztrogonác. + + [Qt] Add DFG module to build system (disabled by default). + https://bugs.webkit.org/show_bug.cgi?id=56845 + + * JavaScriptCore.pri: + * JavaScriptCore.pro: + +2011-03-22 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Add support to build-webkit for building with gyp-generated project files + https://bugs.webkit.org/show_bug.cgi?id=56877 + + Found a couple missing Private headers while trying to make WebCore build. + + * JavaScriptCore.gypi: + +2011-03-22 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Make it possible to build JavaScriptCore and WebCore gyp builds outside of Source + https://bugs.webkit.org/show_bug.cgi?id=56867 + + This should make it possible to build the gyp-generated JavaScriptCore.xcodeproj + from a JavaScriptCore directory outside of Source. + + * gyp/JavaScriptCore.gyp: + * gyp/run-if-exists.sh: Added. + * gyp/update-info-plist.sh: Added. + +2011-03-22 Eric Seidel <eric@webkit.org> + + Reviewed by Adam Barth. + + Add Profiling Configuration to JavaScriptCore gyp build + https://bugs.webkit.org/show_bug.cgi?id=56862 + + It appears this is identical to Release, but I suspect + there is someone/thing who uses the Profiling target + so we're adding it for completeness. + + * gyp/JavaScriptCore.gyp: + +2011-03-22 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Remove os_win32_files variable from the GYP build + https://bugs.webkit.org/show_bug.cgi?id=56804 + + Now that our understanding of GYP is sufficiently advanced, we don't + need os_win32_files any more. (Turns out Eric was right, as he always + is.) + + * JavaScriptCore.gypi: + +2011-03-22 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + GYP build of JavaScriptCore should be able to link from an empty WebKitBuild directory + https://bugs.webkit.org/show_bug.cgi?id=56803 + + Previously, we thought we should generate the derived source files in + the shared intermediate build products directory, but there are + assumptions built into other parts of the Mac build system that the + derived source files will be generated in a particular subdirectory of + the build products directory. + + This patch is a partial revert of the change that moved the derived + source files to the shared intermediate directory. After this patch, + the GYP build can build JavaScriptCore without help from the main + normal build system. + + * JavaScriptCore.gypi: + * gyp/JavaScriptCore.gyp: + * gyp/generate-derived-sources.sh: + * gyp/generate-dtrace-header.sh: + +2011-03-22 Jay Civelli <jcivelli@chromium.org> + + Reviewed by David Levin. + + Adding a contains method to Vector. + https://bugs.webkit.org/show_bug.cgi?id=55859 + + * wtf/Vector.h: + (WTF::Vector::contains): + +2011-03-22 Gabor Loki <loki@webkit.org> + + Reviewed by Alexey Proskuryakov. + + Fix a bunch of typos in DFG. + https://bugs.webkit.org/show_bug.cgi?id=56813 + + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::parse): + * dfg/DFGGenerationInfo.h: + (JSC::DFG::GenerationInfo::setSpilled): + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::dump): + * dfg/DFGGraph.h: + * dfg/DFGJITCodeGenerator.h: + (JSC::DFG::JITCodeGenerator::setupStubArguments): + * dfg/DFGJITCompiler.cpp: + (JSC::DFG::JITCompiler::compileFunction): + * dfg/DFGJITCompiler.h: + * dfg/DFGNode.h: + * dfg/DFGNonSpeculativeJIT.h: + * dfg/DFGOperations.h: + * dfg/DFGRegisterBank.h: + (JSC::DFG::RegisterBank::allocate): + * dfg/DFGScoreBoard.h: + (JSC::DFG::ScoreBoard::~ScoreBoard): + (JSC::DFG::ScoreBoard::allocate): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT.h: + +2011-03-22 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Production configuration in GYP isn't set up correctly + https://bugs.webkit.org/show_bug.cgi?id=56786 + + Update JavaScriptCore.gyp with information mined from + JavaScriptCore.xcodeproj. + + * JavaScriptCore.gypi: + * gyp/JavaScriptCore.gyp: + +2011-03-22 Kent Tamura <tkent@chromium.org> + + Reviewed by Eric Seidel. + + REGRESSION(r80096): Number type input unexpectedly rounds fractional values + https://bugs.webkit.org/show_bug.cgi?id=56367 + + Introduce clampToInteger(unsigned). + + * wtf/MathExtras.h: + (clampToInteger): Added. + +2011-03-21 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + GYP build should not have include paths that point within the source tree + https://bugs.webkit.org/show_bug.cgi?id=56788 + + Turns out we don't need these include paths anymore now that we have + header maps working properly. + + * gyp/JavaScriptCore.gyp: + - Also, remove jsc.cpp from the excluded list because it's not part + of the jsc_files variable instead of the javascriptcore_files + variable. + +2011-03-21 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + Solve the Assertions.cpp / -Wno-missing-format-attribute mystery + https://bugs.webkit.org/show_bug.cgi?id=56780 + + The reason we couldn't resolve this warning in the GYP build was that + the normal build disables this warning specifically for this file. + This patch takes the same approach as the previous patch to + WebCoreObjCExtras.mm in that it uses a pragma to suppress the warning + (rather than a build system configuration). + + * JavaScriptCore.xcodeproj/project.pbxproj: + - Remove the special-case for this file. + * gyp/JavaScriptCore.gyp: + - Remove the work-around for this issue. + * wtf/Assertions.cpp: + - Add a pragma disabling this warning for this file. + +2011-03-21 Adam Barth <abarth@webkit.org> + + Reviewed by Dimitri Glazkov. + + WebCore GYP build shouldn't crash on startup + https://bugs.webkit.org/show_bug.cgi?id=56776 + + Debug builds shouldn't define NDEBUG. This same logic exists in the + project.pbxproj file. + + * gyp/JavaScriptCore.gyp: + +2011-03-21 Robert Kroeger <rjkroege@chromium.org> + + Reviewed by Antonio Gomes. + + Flag to enable/disable a GestureReocognizer framework + + https://bugs.webkit.org/show_bug.cgi?id=49345 + + * wtf/Platform.h: + +2011-03-21 Adam Barth <abarth@webkit.org> + + Reviewed by Dimitri Glazkov. + + Add new files to JavaScriptCore.gypi + https://bugs.webkit.org/show_bug.cgi?id=56766 + + * JavaScriptCore.gypi: + +2011-03-21 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r81377. + http://trac.webkit.org/changeset/81377 + https://bugs.webkit.org/show_bug.cgi?id=56765 + + WebPageSerializerTest.MultipleFrames is broken (Requested by + simonjam on #webkit). + + * wtf/Vector.h: + +2011-03-21 Gabor Loki <loki@webkit.org> + + Reviewed by Csaba Osztrogonác. + + Extend constant pool to be able to store 16 bit instructions with a constant + https://bugs.webkit.org/show_bug.cgi?id=46796 + + The putShortWithConstantInt function inserts a 16 bit instruction which + refers a 32 bits constant or literal. This is a vital function for those + target which loads a PC relative value with a 16 bit instruction (like + Thumb-2 instruction set and SH4 architecture). + + * assembler/AssemblerBuffer.h: + (JSC::AssemblerBuffer::putIntegral): + (JSC::AssemblerBuffer::putIntegralUnchecked): + * assembler/AssemblerBufferWithConstantPool.h: + +2011-03-21 Philippe Normand <pnormand@igalia.com> + + Unreviewed, GTK distcheck build fix. + + * GNUmakefile.am: + +2011-03-20 Bill Budge <bbudge@chromium.org> + + Reviewed by Adam Barth. + + Rename ThreadSafeShared to ThreadSafeRefCounted + https://bugs.webkit.org/show_bug.cgi?id=56714 + + No new tests. Exposes no new functionality. + + * API/JSClassRef.h: + * API/OpaqueJSString.h: + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * wtf/Atomics.h: + * wtf/CMakeLists.txt: + * wtf/CrossThreadRefCounted.h: + (WTF::CrossThreadRefCounted::CrossThreadRefCounted): + (WTF::::crossThreadCopy): + * wtf/ThreadSafeRefCounted.h: Copied from wtf/ThreadSafeShared.h. + (WTF::ThreadSafeRefCountedBase::ThreadSafeRefCountedBase): + (WTF::ThreadSafeRefCountedBase::ref): + (WTF::ThreadSafeRefCountedBase::refCount): + (WTF::ThreadSafeRefCountedBase::derefBase): + (WTF::ThreadSafeRefCounted::ThreadSafeRefCounted): + * wtf/ThreadSafeShared.h: Removed. + * wtf/Threading.h: + +2011-03-19 Patrick Gansterer <paroga@webkit.org> + + Reviewed by Darin Adler. + + Remove StringImpl::computeHash() + https://bugs.webkit.org/show_bug.cgi?id=49894 + + Replace remainig StringImpl::computeHash with StringImpl::computeHashStringHasher. + + * wtf/text/AtomicString.cpp: + (WTF::CStringTranslator::hash): + (WTF::UCharBufferTranslator::hash): + (WTF::HashAndCharactersTranslator::hash): + * wtf/text/StringImpl.h: + (WTF::StringImpl::setHash): + (WTF::StringImpl::hash): + +2011-03-19 Patrick Gansterer <paroga@webkit.org> + + Reviewed by Darin Adler. + + Rename WTF::StringHasher methods + https://bugs.webkit.org/show_bug.cgi?id=53532 + + Rename createHash to computeHash and createBlobHash to hashMemory. + Also add a using WTF::StringHasher in the header file. + + * profiler/CallIdentifier.h: + (JSC::CallIdentifier::Hash::hash): + * runtime/Identifier.cpp: + (JSC::IdentifierCStringTranslator::hash): + (JSC::IdentifierUCharBufferTranslator::hash): + * wtf/StringHasher.h: + (WTF::StringHasher::computeHash): + (WTF::StringHasher::hashMemory): + * wtf/text/StringHash.h: + (WTF::CaseFoldingHash::hash): + * wtf/text/StringImpl.h: + (WTF::StringImpl::computeHash): + * wtf/unicode/UTF8.cpp: + (WTF::Unicode::calculateStringHashAndLengthFromUTF8Internal): + +2011-03-18 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + [GTK] JSC crashes in 32bit Release bots after r80743 + https://bugs.webkit.org/show_bug.cgi?id=56180 + + The crash was caused by referencing GC memory from a GC destructor. This + is not safe because destruction time / order is not guaranteed. + + * profiler/ProfileGenerator.cpp: + (JSC::ProfileGenerator::create): + (JSC::ProfileGenerator::ProfileGenerator): + (JSC::ProfileGenerator::willExecute): + (JSC::ProfileGenerator::didExecute): + * profiler/ProfileGenerator.h: + (JSC::ProfileGenerator::origin): Made ExecState* the first argument, + to match the rest of this class and JSC. + + Use a JSGlobalObject* instead of an ExecState* with an indirect reference + to a JSGlobalObject* to track our origin. This is simpler and more + efficient, and it removes the destruction order dependency that was causing + our crash. + + * profiler/Profiler.cpp: + (JSC::Profiler::startProfiling): Updated for change to JSGlobalObject*. + (JSC::Profiler::stopProfiling): New function for stopping all profiles + for a given global object. This is more straight-forward than multiplexing + through the old function. + + (JSC::dispatchFunctionToProfiles): Updated for change to JSGlobalObject*. + * profiler/Profiler.h: Ditto. + + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::~JSGlobalObject): Ditto. + +2011-03-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + 1 Structure leaked beneath JSGlobalData::storeVPtrs() + https://bugs.webkit.org/show_bug.cgi?id=56595 + + * runtime/Executable.cpp: + (JSC::EvalExecutable::EvalExecutable): + (JSC::ProgramExecutable::ProgramExecutable): + (JSC::FunctionExecutable::FunctionExecutable): + * runtime/Executable.h: + (JSC::ExecutableBase::ExecutableBase): + (JSC::NativeExecutable::NativeExecutable): + (JSC::VPtrHackExecutable::VPtrHackExecutable): + (JSC::ScriptExecutable::ScriptExecutable): Use a raw pointer instead of + PassRefPtr, like JSString does, since JSGlobalData owns the singleton + exectuable structure. + +2011-03-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Mark Rowe. + + Fixed some string leaks seen on the buildbot + https://bugs.webkit.org/show_bug.cgi?id=56619 + + * runtime/PropertyMapHashTable.h: + (JSC::PropertyTable::~PropertyTable): DEref! + +2011-03-17 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + Crash in JSC::MarkStack::drain Under Stress + https://bugs.webkit.org/show_bug.cgi?id=56470 + + We perform a number of gc allocations while when + we are setting up new globals in a piece of global + code. We do this by adding new properties to the + symbol table, and then expanding the storage to fit + at the end. + + If a GC happens during this time we will report an + incorrect size for the global object's symbol table + storage. + + This patch corrects this by growing the storage size + before we starting adding entries to the symbol table. + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::BytecodeGenerator): + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::resizeRegisters): + +2011-03-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + 1 Structure leaked beneath JSGlobalData::storeVPtrs() + https://bugs.webkit.org/show_bug.cgi?id=56595 + + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::storeVPtrs): Take local ownership of the Structure + we're using, since the Executable is not designed to own the Structure. + +2011-03-17 Gavin Barraclough <barraclough@apple.com> + + Rubber Stamped by Sam Weinig. + + Add missing register-register branchTest8 to MacroAssemblerX86Common/X86Assembler. + + * assembler/MacroAssemblerX86Common.h: + (JSC::MacroAssemblerX86Common::branchTest8): + * assembler/X86Assembler.h: + (JSC::X86Assembler::testb_rr): + +2011-03-17 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + Bug 56603 - DFG JIT related cleanup + Move node generation out to separate function, move binarySearch algorithm out + to StdLibExtras, fix Graph::dump() to print comma between non-node children, + even if there are no node children. + + * bytecode/CodeBlock.h: + (JSC::getCallReturnOffset): + (JSC::CodeBlock::getStubInfo): + (JSC::CodeBlock::getCallLinkInfo): + (JSC::CodeBlock::getMethodCallLinkInfo): + (JSC::CodeBlock::bytecodeOffset): + - Move binaryChop to binarySearch in StdLibExtras + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::ByteCodeParser): + (JSC::DFG::ByteCodeParser::parse): + (JSC::DFG::parse): + - Make m_noArithmetic a member, initialize m_currentIndex in the constructor. + * dfg/DFGByteCodeParser.h: + - Change parse() to not take a start index (always 0). + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::dump): + - Fix Graph::dump() to print comma between non-node children, even if there are no node children. + * dfg/DFGJITCodeGenerator.h: + (JSC::DFG::JITCodeGenerator::JITCodeGenerator): + - Initialize m_compileIndex in constructor. + * dfg/DFGNonSpeculativeJIT.cpp: + (JSC::DFG::NonSpeculativeJIT::compile): + * dfg/DFGNonSpeculativeJIT.h: + - Spilt out compilation of individual node. + * dfg/DFGOperations.cpp: + (JSC::DFG::operationConvertThis): + * dfg/DFGOperations.h: + - Cleanup parameter name. + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT.h: + - Spilt out compilation of individual node. + * runtime/Executable.cpp: + (JSC::tryDFGCompile): + - Change parse() to not take a start index (always 0). + * wtf/StdLibExtras.h: + (WTF::binarySearch): + - Move binaryChop to binarySearch in StdLibExtras + +2011-03-17 Anders Carlsson <andersca@apple.com> + + Reviewed by Geoffrey Garen. + + Fix clang build. + + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::storeVPtrs): + +2011-03-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Darin Adler. + + 1 Structure leaked beneath JSGlobalData::storeVPtrs() + https://bugs.webkit.org/show_bug.cgi?id=56595 + + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::storeVPtrs): Now that we have an executable, we need + to explicitly run its destructor. + +2011-03-17 Jeff Miller <jeffm@apple.com> + + Use a consistent set of file patterns in the svn:ignore property for all .xcodeproj directories, specifically: + + *.mode* + *.pbxuser + *.perspective* + project.xcworkspace + xcuserdata + + * JavaScriptCore.xcodeproj: Modified property svn:ignore. + +2011-03-17 Gavin Barraclough <barraclough@apple.com> + + Reverting r81197, breaks JIT + INTERPRETER build. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset): + (JSC::CodeBlock::hasGlobalResolveInfoAtBytecodeOffset): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::addPropertyAccessInstruction): + (JSC::CodeBlock::addGlobalResolveInstruction): + (JSC::CodeBlock::addStructureStubInfo): + * bytecode/Opcode.h: + * bytecode/StructureStubInfo.h: + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitResolve): + (JSC::BytecodeGenerator::emitResolveWithBase): + (JSC::BytecodeGenerator::emitGetById): + (JSC::BytecodeGenerator::emitPutById): + (JSC::BytecodeGenerator::emitDirectPutById): + (JSC::BytecodeGenerator::emitCall): + (JSC::BytecodeGenerator::emitConstruct): + (JSC::BytecodeGenerator::emitCatch): + +2011-03-17 Ben Taylor <bentaylor.solx86@gmail.com> + + Reviewed by Alexey Proskuryakov. + + Add a COMPILER(SUNCC) define for Sun Studio 12. + https://bugs.webkit.org/show_bug.cgi?56444 + derived from patch 1 of 16 originally from https://bugs.webkit.org/show_bug.cgi?id=24932 + + * wtf/Platform.h: + +2011-03-17 Jay Civelli <jcivelli@chromium.org> + + Reviewed by David Levin. + + Adding a contains method to Vector. + https://bugs.webkit.org/show_bug.cgi?id=55859 + + * wtf/Vector.h: + (WTF::::operator): + (WTF::::contains): + +2011-03-17 Patrick Gansterer <paroga@webkit.org> + + Fix the interpreter build. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): Added globalData to inheritorID(). + +2011-03-16 Sam Weinig <sam@webkit.org> + + Fix the interpreter build. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::resolve): + (JSC::Interpreter::resolveSkip): + (JSC::Interpreter::resolveGlobal): + (JSC::Interpreter::resolveGlobalDynamic): + (JSC::Interpreter::resolveBaseAndProperty): + (JSC::Interpreter::privateExecute): + Remove .get()s. + +2011-03-16 Adam Barth <abarth@webkit.org> + + Reviewed by James Robinson. + + Remove USE(BUILTIN_UTF8_CODEC) + https://bugs.webkit.org/show_bug.cgi?id=56508 + + We added this recently when we were unsure about the stability of the + built-in UTF-8 codec. However, the codec seems to be stable, so we + don't need the macro. + + * wtf/Platform.h: + +2011-03-16 Daniel Bates <dbates@rim.com> + + Reviewed by Darin Adler. + + Make JIT build for ARM Thumb-2 with RVCT + https://bugs.webkit.org/show_bug.cgi?id=56440 + + Derived from a patch by Dave Tapuska. + + Also, modify the RVCT stub template to indicate that it preserves 8 byte stack alignment. + + * jit/JITStubs.cpp: + +2011-03-16 Chao-ying Fu <fu@mips.com> + + Reviewed by Darin Adler. + + Fix MIPS build with const *void + https://bugs.webkit.org/show_bug.cgi?id=56513 + + * assembler/MacroAssemblerMIPS.h: + (JSC::MacroAssemblerMIPS::load32): + (JSC::MacroAssemblerMIPS::store32): + +2011-03-16 Oliver Hunt <oliver@apple.com> + + Reviewed by Darin Adler. + + Remove unnecessary caller tracking shenanigans from CodeBlock + https://bugs.webkit.org/show_bug.cgi?id=56483 + + This removes some leftover cruft from when we made CodeBlock + mark its callees. Removing it gives us a 0.7% progression, + reducing the overall regression to ~1.3%. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::shrinkToFit): + * bytecode/CodeBlock.h: + (JSC::CallLinkInfo::CallLinkInfo): + * jit/JIT.cpp: + (JSC::JIT::linkCall): + (JSC::JIT::linkConstruct): + +2011-03-15 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + Make Structure creation require a JSGlobalData + https://bugs.webkit.org/show_bug.cgi?id=56438 + + Mechanical change to make Structure::create require JSGlobalData&, and + require all users to provide the globalData. + + * API/JSCallbackConstructor.h: + (JSC::JSCallbackConstructor::createStructure): + * API/JSCallbackFunction.h: + (JSC::JSCallbackFunction::createStructure): + * API/JSCallbackObject.h: + (JSC::JSCallbackObject::createStructure): + * API/JSContextRef.cpp: + * JavaScriptCore.exp: + * debugger/DebuggerActivation.cpp: + (JSC::DebuggerActivation::DebuggerActivation): + * debugger/DebuggerActivation.h: + (JSC::DebuggerActivation::createStructure): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * jsc.cpp: + (GlobalObject::GlobalObject): + (functionRun): + (jscmain): + * runtime/Arguments.h: + (JSC::Arguments::createStructure): + * runtime/ArrayPrototype.h: + (JSC::ArrayPrototype::createStructure): + * runtime/BooleanObject.h: + (JSC::BooleanObject::createStructure): + * runtime/DateInstance.h: + (JSC::DateInstance::createStructure): + * runtime/DatePrototype.h: + (JSC::DatePrototype::createStructure): + * runtime/ErrorInstance.h: + (JSC::ErrorInstance::createStructure): + * runtime/Executable.h: + (JSC::ExecutableBase::createStructure): + (JSC::EvalExecutable::createStructure): + (JSC::ProgramExecutable::createStructure): + (JSC::FunctionExecutable::createStructure): + * runtime/FunctionPrototype.h: + (JSC::FunctionPrototype::createStructure): + * runtime/GetterSetter.h: + (JSC::GetterSetter::createStructure): + * runtime/InternalFunction.h: + (JSC::InternalFunction::createStructure): + * runtime/JSAPIValueWrapper.h: + (JSC::JSAPIValueWrapper::createStructure): + * runtime/JSActivation.h: + (JSC::JSActivation::createStructure): + * runtime/JSArray.cpp: + (JSC::JSArray::JSArray): + * runtime/JSArray.h: + (JSC::JSArray::createStructure): + * runtime/JSByteArray.cpp: + (JSC::JSByteArray::createStructure): + * runtime/JSByteArray.h: + (JSC::JSByteArray::JSByteArray): + * runtime/JSCell.h: + (JSC::JSCell::JSCell::createDummyStructure): + * runtime/JSFunction.h: + (JSC::JSFunction::createStructure): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::storeVPtrs): + (JSC::JSGlobalData::JSGlobalData): + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::reset): + * runtime/JSGlobalObject.h: + (JSC::JSGlobalObject::JSGlobalObject): + (JSC::JSGlobalObject::createStructure): + * runtime/JSNotAnObject.h: + (JSC::JSNotAnObject::createStructure): + * runtime/JSONObject.h: + (JSC::JSONObject::createStructure): + * runtime/JSObject.cpp: + (JSC::JSObject::createInheritorID): + * runtime/JSObject.h: + (JSC::JSObject::createStructure): + (JSC::JSNonFinalObject::createStructure): + (JSC::JSFinalObject::createStructure): + (JSC::createEmptyObjectStructure): + (JSC::JSObject::inheritorID): + * runtime/JSObjectWithGlobalObject.h: + (JSC::JSObjectWithGlobalObject::createStructure): + * runtime/JSPropertyNameIterator.h: + (JSC::JSPropertyNameIterator::createStructure): + * runtime/JSStaticScopeObject.h: + (JSC::JSStaticScopeObject::createStructure): + * runtime/JSString.h: + (JSC::RopeBuilder::createStructure): + * runtime/JSVariableObject.h: + (JSC::JSVariableObject::createStructure): + * runtime/JSWrapperObject.h: + (JSC::JSWrapperObject::createStructure): + * runtime/JSZombie.h: + (JSC::JSZombie::createStructure): + * runtime/MathObject.h: + (JSC::MathObject::createStructure): + * runtime/NativeErrorConstructor.cpp: + (JSC::NativeErrorConstructor::NativeErrorConstructor): + * runtime/NativeErrorConstructor.h: + (JSC::NativeErrorConstructor::createStructure): + * runtime/NumberConstructor.h: + (JSC::NumberConstructor::createStructure): + * runtime/NumberObject.h: + (JSC::NumberObject::createStructure): + * runtime/ObjectConstructor.h: + (JSC::ObjectConstructor::createStructure): + * runtime/RegExpConstructor.h: + (JSC::RegExpConstructor::createStructure): + * runtime/RegExpObject.h: + (JSC::RegExpObject::createStructure): + * runtime/ScopeChain.h: + (JSC::ScopeChainNode::createStructure): + * runtime/StringObject.h: + (JSC::StringObject::createStructure): + * runtime/StringObjectThatMasqueradesAsUndefined.h: + (JSC::StringObjectThatMasqueradesAsUndefined::createStructure): + * runtime/StringPrototype.h: + (JSC::StringPrototype::createStructure): + * runtime/Structure.h: + (JSC::Structure::create): + +2011-03-16 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Some conservative root gathering cleanup + https://bugs.webkit.org/show_bug.cgi?id=56447 + + SunSpider says 0.5% - 1.8% faster. + + * interpreter/RegisterFile.cpp: + (JSC::RegisterFile::gatherConservativeRoots): + * interpreter/RegisterFile.h: New helper function for doing the + conservative gathering of the register file. It's still conservative, + since the register file may contain uninitialized values, but it's + moving-safe, because it only visits values tagged as pointers, so there's + no risk of mistaking an integer for a pointer and accidentally changing it. + + * runtime/ConservativeSet.cpp: + (JSC::ConservativeRoots::add): + * runtime/ConservativeSet.h: Added a single-value add function, used above. + + * runtime/Heap.cpp: + (JSC::Heap::markRoots): Separated machine stack conservative roots from + register file conservative roots because machine stack roots must be + pinned, but register file roots need not be pinned. + + Adopted new interface for passing the current stack extent to the machine + stack root gathering routine. This allows us to exclude marking-related + data structures on the stack, and thus avoid double-marking the set of + machine roots. + + * runtime/MachineStackMarker.cpp: + (JSC::MachineThreads::gatherFromCurrentThread): + (JSC::MachineThreads::gatherConservativeRoots): + * runtime/MachineStackMarker.h: Added new interface, described above. + + * runtime/MarkedBlock.h: + (JSC::MarkedBlock::firstAtom): + * wtf/StdLibExtras.h: + (WTF::roundUpToMultipleOf): Moved roundUpToMultipleOf so it could be used + by MachineStacks. + +2011-03-16 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + A little bit of MarkStack cleanup + https://bugs.webkit.org/show_bug.cgi?id=56443 + + Moved MarkStack functions into MarkStack.h/.cpp. + + SunSpider reports no change. + + * runtime/JSArray.h: + * runtime/JSCell.h: Moved from here... + * runtime/MarkStack.cpp: + (JSC::MarkStack::markChildren): + (JSC::MarkStack::drain): ...to here. Also, no need to inline drain. It's + a huge function, and not called many times. + + * runtime/MarkStack.h: + (JSC::MarkStack::~MarkStack): Moved near constructor, per style guide. + (JSC::MarkStack::append): + (JSC::MarkStack::deprecatedAppend): + (JSC::MarkStack::internalAppend): Moved to here. + +2011-03-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Removed another deprecatedAppend + https://bugs.webkit.org/show_bug.cgi?id=56429 + + * collector/handles/HandleHeap.cpp: + (JSC::HandleHeap::markStrongHandles): + * collector/handles/HandleHeap.h: Use HeapRootMarker, since handles are + marked directly by the Heap. + + * runtime/Heap.cpp: + (JSC::Heap::markRoots): Ditto. + +2011-03-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Removed some more deprecated / unsafe append + https://bugs.webkit.org/show_bug.cgi?id=56428 + + * collector/handles/HandleStack.cpp: + (JSC::HandleStack::mark): + * collector/handles/HandleStack.h: Mark the handle stack using a HeapRoot + marker, since it's a heap root. + + * runtime/ArgList.cpp: + (JSC::MarkedArgumentBuffer::markLists): + (JSC::MarkedArgumentBuffer::slowAppend): + * runtime/ArgList.h: Ditto. + + * runtime/Heap.cpp: + (JSC::Heap::markRoots): Added a mark call for marking the handle stack. + It seems like Oliver forgot this in his last patch. (!) + + * runtime/MarkStack.h: Removed appendSlots, since it would allow an + object to embed JSValues directly instead of using WriteBarrier. + + (JSC::MarkStack::append): Added a private append for a list of values. + + (JSC::HeapRootMarker::mark): Access to the above. + +2011-03-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Removed a few more deprecatedAppends, and removed HeapRoot<T> + https://bugs.webkit.org/show_bug.cgi?id=56422 + + Added HeapRootMarker, a privileged class for marking direct heap roots + that are iterated during each garbage collection. This is easier to use + and more reliable than HeapRoot<T>, so I've removed HeapRoot<T>. + + * debugger/Debugger.cpp: + (JSC::evaluateInGlobalCallFrame): + * debugger/DebuggerCallFrame.cpp: + (JSC::DebuggerCallFrame::evaluate): + * interpreter/CallFrame.h: + (JSC::ExecState::exception): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * runtime/Completion.cpp: + (JSC::evaluate): exception is no longer a HeapRoot<T>, so no need to + call .get() on it. + + * runtime/Heap.cpp: + (JSC::Heap::markProtectedObjects): + (JSC::Heap::markTempSortVectors): + (JSC::Heap::markRoots): + * runtime/Heap.h: Updated to use HeapRootMarker. + + * runtime/JSCell.h: + (JSC::JSCell::MarkStack::append): Added private functions for + HeapRootMarker to use. + + * runtime/JSGlobalData.h: exception is no longer a HeapRoot<T>. + + * runtime/MarkStack.h: + (JSC::HeapRootMarker::HeapRootMarker): + (JSC::HeapRootMarker::mark): Added private functions for + HeapRootMarker to use. + + * runtime/SmallStrings.cpp: + (JSC::SmallStrings::markChildren): Updated to use HeapRootMarker. + + * runtime/SmallStrings.h: + (JSC::SmallStrings::emptyString): + (JSC::SmallStrings::singleCharacterString): + (JSC::SmallStrings::singleCharacterStrings): Updated to use HeapRootMarker. + + * runtime/WriteBarrier.h: Removed HeapRoot<T>. + +2011-03-14 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Made the global object moving-GC-safe + https://bugs.webkit.org/show_bug.cgi?id=56348 + + SunSpider reports no change. + + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::markChildren): Removed a dubious comment that + suggested we do not need to visit all our references during GC, since + that is not true in a moving GC. + + Re-sorted data members by type, removed one duplicate, and added back + the one missing mark I found. + + * runtime/JSGlobalObject.h: Re-sorted data members by type. + +2011-03-15 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + Introduce Local<T> to allow us to start moving to precise marking of locals + https://bugs.webkit.org/show_bug.cgi?id=56394 + + Introduce a new handle type, Local<T> and a scoping mechanism + LocalScope to allow us to start moving towards precise marking + of temporaries and local variables. + + We also start to use the new Local<> type in the JSON stringifier + so that we can have some coverage of their behaviour in the initial + checkin. + + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.pro: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * collector/handles/Handle.h: + (JSC::::asObject): + * collector/handles/HandleStack.cpp: Added. + (JSC::HandleStack::HandleStack): + (JSC::HandleStack::mark): + (JSC::HandleStack::grow): + * collector/handles/HandleStack.h: Added. + (JSC::HandleStack::enterScope): + (JSC::HandleStack::zapTo): + (JSC::HandleStack::leaveScope): + (JSC::HandleStack::push): + * collector/handles/Local.h: Added. + (JSC::Local::internalSet): + (JSC::::Local): + (JSC::::operator): + (JSC::LocalStack::LocalStack): + (JSC::LocalStack::peek): + (JSC::LocalStack::pop): + (JSC::LocalStack::push): + (JSC::LocalStack::isEmpty): + (JSC::LocalStack::size): + * collector/handles/LocalScope.h: Added. + (JSC::LocalScope::LocalScope): + (JSC::LocalScope::~LocalScope): + (JSC::LocalScope::release): + * runtime/Heap.cpp: + (JSC::Heap::markRoots): + * runtime/Heap.h: + (JSC::Heap::allocateLocalHandle): + (JSC::Heap::handleStack): + * runtime/JSCell.h: + (JSC::JSCell::::getString): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + * runtime/JSGlobalData.h: + (JSC::JSGlobalData::allocateLocalHandle): + * runtime/JSONObject.cpp: + (JSC::Stringifier::Stringifier): + (JSC::Stringifier::stringify): + (JSC::Stringifier::appendStringifiedValue): + (JSC::Stringifier::Holder::Holder): + (JSC::Walker::Walker): + (JSC::Walker::walk): + (JSC::JSONProtoFuncParse): + (JSC::JSONProtoFuncStringify): + (JSC::JSONStringify): + * runtime/JSONObject.h: + * runtime/MarkStack.h: + (JSC::MarkStack::appendValues): + (JSC::MarkStack::appendSlots): + +2011-03-15 Gavin Barraclough <barraclough@apple.com> + + Rubber Stamped by Sam Weinig. + + Bug 56420 - Remove ENABLE(JIT) code from ByteCompiler + Some methods have unnecessary differences in name/arguments for interpreter/JIT. + + * bytecode/CodeBlock.cpp: + * bytecode/CodeBlock.h: + (JSC::HandlerInfo::HandlerInfo): + (JSC::CodeBlock::addPropertyAccessInfo): + (JSC::CodeBlock::addGlobalResolveInfo): + (JSC::CodeBlock::addCallLinkInfo): + (JSC::CodeBlock::globalResolveInfo): + * bytecode/Opcode.h: + * bytecode/StructureStubInfo.h: + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitResolve): + (JSC::BytecodeGenerator::emitResolveWithBase): + (JSC::BytecodeGenerator::emitGetById): + (JSC::BytecodeGenerator::emitPutById): + (JSC::BytecodeGenerator::emitDirectPutById): + (JSC::BytecodeGenerator::emitCall): + (JSC::BytecodeGenerator::emitConstruct): + (JSC::BytecodeGenerator::emitCatch): + +2011-03-15 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + Fix broken assert in new code. + + * dfg/DFGAliasTracker.h: + (JSC::DFG::AliasTracker::recordPutByVal): + - recordPutByVal is called for both PutByVal & PutByValAlias. + +2011-03-15 Gavin Barraclough <barraclough@apple.com> + + Rubber stamped by Sam Weinig. + + Removed redundant code from BytecodeGenerator. + + * bytecompiler/BytecodeGenerator.cpp: + * bytecompiler/BytecodeGenerator.h: + - delete uncalled code missed when reparsing was removed. + +2011-03-15 Kevin Ollivier <kevino@theolliviers.com> + + Reviewed by Darin Adler. + + Introduce WTF_USE_EXPORT_MACROS, which will allow us to put shared library import/export + info into the headers rather than in export symbol definition files, but disable it on + all platforms initially so we can deal with port build issues one port at a time. + + https://bugs.webkit.org/show_bug.cgi?id=27551 + + * API/JSBase.h: + * config.h: + * wtf/Assertions.h: + * wtf/ExportMacros.h: Added. + * wtf/Platform.h: + +2011-03-14 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Unreviewed build fix. + + Buildfix when JIT is not enabled after r81079 + https://bugs.webkit.org/show_bug.cgi?id=56361 + + * runtime/Executable.cpp: + +2011-03-14 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Made the global object moving-GC-safe + https://bugs.webkit.org/show_bug.cgi?id=56348 + + SunSpider reports no change. + + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::markChildren): Removed a dubious comment that + suggested we do not need to visit all our references during GC, since + that is not true in a moving GC. + + Re-sorted data members by type, removed one duplicate, and added back + the one missing mark I found. + + * runtime/JSGlobalObject.h: Re-sorted data members by type. + +2011-03-14 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Made JSWrapperObject and subclasses moving-GC-safe + https://bugs.webkit.org/show_bug.cgi?id=56346 + + SunSpider reports no change. + + * runtime/BooleanObject.cpp: + (JSC::BooleanObject::BooleanObject): + * runtime/DateInstance.cpp: + (JSC::DateInstance::DateInstance): No more need for JSGlobalData, since + we don't initialize the wrapped value in our constructor. + + * runtime/DateInstance.h: Don't set the OverridesMarkChildren flag because + we do not in fact override markChildren. + + * runtime/DatePrototype.h: Declare an anonymous slot, since wrapper object + no longer does so for us. Also added an ASSERT to catch a latent bug, + where DatePrototype stomped on its base class's anonymous slot. Hard-coded + anonymous slots are a plague on our code. This doesn't cause any problems + in our existing code since the base class never reads the anonymous slot + it declares, but it caused crashes when I tried to start using the slot + in an initial version of this patch. + + * runtime/JSWrapperObject.h: + (JSC::JSWrapperObject::JSWrapperObject): + (JSC::JSWrapperObject::internalValue): + (JSC::JSWrapperObject::setInternalValue): Resolved a problem where + our internal value was stored in two places: an anonymous slot, and a + data member which was not always visited during GC. Now, we only use the + data member, and we always visit it. (Instead of relying on certain + subclasses to set the OverridesMarkChildren bit, we set it ourselves.) + + * runtime/NumberObject.cpp: + (JSC::NumberObject::NumberObject): No more need for JSGlobalData, since + we don't initialize the wrapped value in our constructor. + + * runtime/NumberObject.h: Removed meaningless declaration. + + * runtime/StringObject.cpp: + (JSC::StringObject::StringObject): No more need for JSGlobalData, since + we don't initialize the wrapped value in our constructor. + + * runtime/StringObject.h: Don't set the OverridesMarkChildren flag because + we do not in fact override markChildren. + + * runtime/StringPrototype.h: Declare an anonymous slot, since wrapper object + no longer does so for us. Also added an ASSERT to catch a latent bug, + where DatePrototype stomped on its base class's anonymous slot. Hard-coded + anonymous slots are a plague on our code. + +2011-03-14 Michael Saboff <msaboff@apple.com> + + Reviewed by Gavin Barraclough. + + Look-ahead assertions with back references don’t work as expected + https://bugs.webkit.org/show_bug.cgi?id=56082 + + Changed parentheses assertion processing to temporarily back out the + number of known characters after the assertion while processing the + assertion. This was done so that assertions don't fail due to + checking the number of required characters as additional to the + rest of the express since assertions don't "consume" input. + Added a byte code to uncheck characters to support the change. + + * yarr/YarrInterpreter.cpp: + (JSC::Yarr::Interpreter::matchDisjunction): + (JSC::Yarr::ByteCompiler::uncheckInput): + (JSC::Yarr::ByteCompiler::emitDisjunction): + * yarr/YarrInterpreter.h: + (JSC::Yarr::ByteTerm::UncheckInput): + +2011-03-14 Viatcheslav Ostapenko <ostapenko.viatcheslav@nokia.com> + + Reviewed by Laszlo Gombos. + + [Qt] Warning that round/roundf functions are already defined when compiled with RVCT 4 on symbian. + https://bugs.webkit.org/show_bug.cgi?id=56133 + + Add condition to not compile webkit internal math round functions on RVCT compiler versions + from 3.0.0 because they are already defined in compiler math library. + + * wtf/MathExtras.h: + +2011-03-14 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoffrey Garen & Oliver Hunt. + + Bug 56284 - Add a dataflow intermediate representation for use in JIT generation. + + The JSC JIT presently generates code directly from the bytecode used by the interpreter. + This is not an optimal intermediate representation for JIT code generation, since it does + not capture liveness information of values, and provides little opportunity to perform + any static analysis for even primitive types. The JIT currently generates two code paths, + a fast path handling common cases, and a slower path handling less common operand types. + However the slow path jumps back into the fast path, meaning that information arising + from the earlier type checks cannot be propagated to later operations. + + This patch adds: + * a dataflow intermediate representation capable of describing a single basic block + of operations, + * a mechanism to convert a simple, single-block bytecode functions to the new IR, + * and a JIT code generator capable of generating code from this representation. + + The JIT generates two code paths, with the slower path not reentering the fast path + mid-block, allowing speculative optimizations to be made on the hot path, with type + information arising from these speculative decisions able to be propagated through the + dataflow. Code generation of both speculative and non-speculative paths exploits the type + and liveness information represented in the dataflow graph to attempt to avoid redundant + boxing and type-checking of values, and to remove unnecessary spills of temporary values + to the RegisterFile. + + The dataflow JIT currently can only support a subset of bytecode operations, limited to + arithmetic, bit-ops, and basic property access. Functions that cannot be compiled by the + dataflow JIT will be run using the existing JIT. The coverage of the dataflow JIT will be + expanded to include, control-flow, function calls, and then the long-tail of remaining + bytecode instructions. The JIT presently only support JSVALUE64, and as a consequence of + this only supports x86-64. + + The status of the dataflow JIT is currently work-in-progress. Limitations of the present + JIT code generation may cause performance regressions, particularly: + * the policy to only generate arithmetic code on the speculative path using integer + instructions, never using floating point. + * the policy to only generate arithmetic code on the non-speculative path using + floating point instructions, never using integer. + * always generating JSValue adds on the non-speculative path as a call out to a + C-function, never handling this in JIT code. + * always assuming by-Value property accesses on the speculative path to be array + accesses. + * generating all by-Value property accesses from the non-speculative path as a call + out to a C-function. + * generating all by-Indentifer property accesses as a call out to a C-function. + Due to these regressions, the code is landed in a state where it is disabled in most + cases by the ENABLE_DFG_JIT_RESTRICTIONS guard in Platform.h. As these regressions are + addressed, the JIT will be allowed to trigger in more cases. + + * JavaScriptCore.xcodeproj/project.pbxproj: + - Added new files to Xcode project. + * dfg: Added. + - Added directory for new code. + * dfg/DFGByteCodeParser.cpp: Added. + * dfg/DFGByteCodeParser.h: Added. + - Contruct a DFG::Graph representation from a bytecode CodeBlock. + * dfg/DFGGenerationInfo.h: Added. + - Track type & register information for VirtualRegisters during JIT code generation. + * dfg/DFGGraph.cpp: Added. + * dfg/DFGGraph.h: Added. + - Dataflow graph intermediate representation for code generation. + * dfg/DFGJITCodeGenerator.cpp: Added. + * dfg/DFGJITCodeGenerator.h: Added. + - Base class for SpeculativeJIT & NonSpeculativeJIT to share common functionality. + * dfg/DFGJITCompiler.cpp: Added. + * dfg/DFGJITCompiler.h: Added. + - Class responsible for driving code generation of speculativeJIT & non-speculative + code paths from the dataflow graph. + * dfg/DFGNonSpeculativeJIT.cpp: Added. + * dfg/DFGNonSpeculativeJIT.h: Added. + - Used to generate the non-speculative code path, this make no assumptions + about operand types. + * dfg/DFGOperations.cpp: Added. + * dfg/DFGOperations.h: Added. + - Helper functions called from the JIT generated code. + * dfg/DFGRegisterBank.h: Added. + - Used to track contents of physical registers during JIT code generation. + * dfg/DFGSpeculativeJIT.cpp: Added. + * dfg/DFGSpeculativeJIT.h: Added. + - Used to generate the speculative code path, this make assumptions about + operand types to enable optimization. + * runtime/Executable.cpp: + - Add code to attempt to use the DFG JIT to compile a function, with fallback + to the existing JIT. + * wtf/Platform.h: + - Added compile guards to enable the DFG JIT. + +2011-03-14 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Removed more cases of DeprecatedPtr (exception, SmallStrings) + https://bugs.webkit.org/show_bug.cgi?id=56332 + + * runtime/Identifier.cpp: + (JSC::Identifier::add): + (JSC::Identifier::addSlowCase): Use a variable instead of a hard-coded + constant, to make this code less brittle. + + * runtime/JSGlobalData.h: Use HeapRoot instead of DeprecatedPtr because + this reference is owned and managed directly by the heap. + + * runtime/JSString.cpp: + (JSC::JSString::substringFromRope): + * runtime/JSString.h: + (JSC::jsSingleCharacterString): + (JSC::jsSingleCharacterSubstring): + (JSC::jsString): + (JSC::jsStringWithFinalizer): + (JSC::jsSubstring): + (JSC::jsOwnedString): Use a variable instead of a hard-coded + constant, to make this code less brittle. + + * runtime/SmallStrings.cpp: + (JSC::SmallStringsStorage::rep): + (JSC::SmallStringsStorage::SmallStringsStorage): + (JSC::SmallStrings::SmallStrings): + (JSC::SmallStrings::markChildren): + (JSC::SmallStrings::clear): + (JSC::SmallStrings::count): Use a variable instead of a hard-coded + constant, to make this code less brittle. + + * runtime/SmallStrings.h: + (JSC::SmallStrings::singleCharacterString): Use HeapRoot instead of + DeprecatedPtr because these references are owned and managed directly by + the heap. + + Stop using FixedArray because we only want a very limited set + of classes to be able to use HeapRoot. (Replaced with manual ASSERTs.) + + * runtime/WriteBarrier.h: + (JSC::operator==): + (JSC::WriteBarrier::WriteBarrier): + (JSC::HeapRoot::HeapRoot): + (JSC::HeapRoot::operator=): Added HeapRoot, which is allowed to set + without write barrier because we assume all HeapRoots are scanned during + all GC passes. + +2011-03-14 Brian Weinstein <bweinstein@apple.com> + + Reviewed by Adam Roben and Gavin Barraclough. + + FileSystemWin.cpp needs listDirectory() implementation + https://bugs.webkit.org/show_bug.cgi?id=56331 + <rdar://problem/9126635> + + Give StringConcatenate the ability to deal with const UChar*'s as a String type to append. + + * wtf/text/StringConcatenate.h: + +2011-03-14 Mark Rowe <mrowe@apple.com> + + Reviewed by Oliver Hunt. + + <http://webkit.org/b/56304> REGRESSION(r80892): 100,000+ leaks seen on the build bot + + * API/JSClassRef.cpp: + (OpaqueJSClass::OpaqueJSClass): Don't leak any existing entry for the given name if + the class definition contains duplicates. This also removes what look to be leaks + of the StringImpl instances that are used as keys: the HashMap key type is a RefPtr + which retains / releases the instances at the appropriate time, so explicitly calling + ref is not necessary. + +2011-03-14 Oliver Hunt <oliver@apple.com> + + Fix windows build + + * jit/JSInterfaceJIT.h: + (JSC::JSInterfaceJIT::emitLoadInt32): + (JSC::JSInterfaceJIT::tagFor): + (JSC::JSInterfaceJIT::payloadFor): + (JSC::JSInterfaceJIT::intPayloadFor): + (JSC::JSInterfaceJIT::intTagFor): + (JSC::JSInterfaceJIT::addressFor): + +2011-03-11 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Ensure all values are correctly tagged in the registerfile + https://bugs.webkit.org/show_bug.cgi?id=56214 + + This patch makes sure that all JSCell pointers written to + the registerfile are correctly tagged as JSCells, and replaces + raw int usage with the immediate representation. + + For performance, register pressure, and general saneness reasons + I've added abstractions for reading and writing the tag + and payload of integer registers directly for the JSVALUE64 + encoding. + + * interpreter/Register.h: + (JSC::Register::withInt): + (JSC::Register::withCallee): + (JSC::Register::operator=): + (JSC::Register::i): + (JSC::Register::activation): + (JSC::Register::function): + (JSC::Register::propertyNameIterator): + (JSC::Register::scopeChain): + * jit/JIT.h: + * jit/JITCall.cpp: + (JSC::JIT::compileOpCallInitializeCallFrame): + (JSC::JIT::compileOpCallVarargs): + (JSC::JIT::compileOpCall): + * jit/JITCall32_64.cpp: + (JSC::JIT::compileOpCallInitializeCallFrame): + (JSC::JIT::compileOpCallVarargs): + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpCallSlowCase): + * jit/JITInlineMethods.h: + (JSC::JIT::emitPutToCallFrameHeader): + (JSC::JIT::emitPutCellToCallFrameHeader): + (JSC::JIT::emitPutIntToCallFrameHeader): + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTINativeCall): + (JSC::JIT::emit_op_get_pnames): + (JSC::JIT::emit_op_next_pname): + (JSC::JIT::emit_op_load_varargs): + (JSC::JIT::emitSlow_op_load_varargs): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::privateCompileCTINativeCall): + (JSC::JIT::emit_op_get_pnames): + (JSC::JIT::emit_op_next_pname): + * jit/JSInterfaceJIT.h: + (JSC::JSInterfaceJIT::intPayloadFor): + (JSC::JSInterfaceJIT::intTagFor): + * jit/SpecializedThunkJIT.h: + (JSC::SpecializedThunkJIT::returnJSValue): + (JSC::SpecializedThunkJIT::returnDouble): + (JSC::SpecializedThunkJIT::returnInt32): + (JSC::SpecializedThunkJIT::returnJSCell): + +2011-03-13 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + A few Heap-related renames (sans file moves, which should come next) + https://bugs.webkit.org/show_bug.cgi?id=56283 + + ConservativeSet => ConservativeRoots. "Set" was misleading, since items + are not uniqued. Also, "Roots" is more specific about what's in the set. + + MachineStackMarker => MachineThreads. "Threads" is more descriptive of + the fact that this class maintains a set of all threads using JSC. + "Stack" was misleading, since this class traverses stacks and registers. + "Mark" was misleading, since this class doesn't mark anything anymore. + + registerThread => addCurrentThread. "Current" is more specific. + unregisterThread => removeCurrentThread. "Current" is more specific. + + "currentThreadRegistrar" => threadSpecific. The only point of this data + structure is to register a thread-specific destructor with a pointer to + this. + + "mark...Conservatively" => "gather". "Mark" is not true, since these + functions don't mark anything. "Conservatively" is redundant, since they + take "ConservativeRoots" as an argument. + + * API/APIShims.h: + (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): + * JavaScriptCore.exp: + * runtime/ConservativeSet.cpp: + (JSC::ConservativeRoots::grow): + (JSC::ConservativeRoots::add): + * runtime/ConservativeSet.h: + (JSC::ConservativeRoots::ConservativeRoots): + (JSC::ConservativeRoots::~ConservativeRoots): + (JSC::ConservativeRoots::size): + (JSC::ConservativeRoots::roots): + * runtime/Heap.cpp: + (JSC::Heap::Heap): + (JSC::Heap::markRoots): + * runtime/Heap.h: + (JSC::Heap::machineThreads): + * runtime/JSGlobalData.h: + (JSC::JSGlobalData::makeUsableFromMultipleThreads): + * runtime/MachineStackMarker.cpp: + (JSC::MachineThreads::MachineThreads): + (JSC::MachineThreads::~MachineThreads): + (JSC::MachineThreads::makeUsableFromMultipleThreads): + (JSC::MachineThreads::addCurrentThread): + (JSC::MachineThreads::removeThread): + (JSC::MachineThreads::removeCurrentThread): + (JSC::MachineThreads::gatherFromCurrentThreadInternal): + (JSC::MachineThreads::gatherFromCurrentThread): + (JSC::MachineThreads::gatherFromOtherThread): + (JSC::MachineThreads::gatherConservativeRoots): + * runtime/MachineStackMarker.h: + * runtime/MarkStack.h: + (JSC::MarkStack::append): + +2011-03-13 David Kilzer <ddkilzer@apple.com> + + BUILD FIX for armv7 after r80969 + + Bug 56270 - The JIT 'friend's many classes in JSC; start unwinding this. + <https://bugs.webkit.org/show_bug.cgi?id=56270> + + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::load32): Made void* address argument + const. + (JSC::MacroAssemblerARMv7::store32): Ditto. + +2011-03-13 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Try to fix the Mac build. + + * JavaScriptCore.xcodeproj/project.pbxproj: Make sure to forward + ConervativeSet.h, since it's now visible when compiling other projects. + +2011-03-13 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Removed another case of DeprecatedPtr (ConservativeSet) + https://bugs.webkit.org/show_bug.cgi?id=56281 + + The ConservativeSet is an internal data structure used during marking, + so direct pointers are fine. + + * runtime/ConservativeSet.cpp: + (JSC::ConservativeSet::grow): + * runtime/ConservativeSet.h: Added some accessors, for use by MarkStack::append. + (JSC::ConservativeSet::~ConservativeSet): Fixed a typo where we calculated + the size of the set based on sizeof(DeprecatedPtr<T>*) instead of + sizeof(DeprecatedPtr<T>). I'm not sure if this had real-world implications or not. + (JSC::ConservativeSet::size): + (JSC::ConservativeSet::set): Use direct pointers, as stated above. + + * runtime/Heap.cpp: + (JSC::Heap::markRoots): + * runtime/MarkStack.h: + (JSC::MarkStack::append): Created a special case of append for + ConservativeSet. I didn't want to add back a generic "append JSCell*" + function, since other class might start using that wrong. (In the end, + this function might go away, since the Heap will want to do something + slightly more interesting with the conservative set, but this is OK for + now.) + +2011-03-13 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Removed another case of DeprecatedPtr (PutPropertySlot) + https://bugs.webkit.org/show_bug.cgi?id=56278 + + * runtime/PutPropertySlot.h: + (JSC::PutPropertySlot::setExistingProperty): + (JSC::PutPropertySlot::setNewProperty): + (JSC::PutPropertySlot::base): Direct pointer is fine for PutPropertySlot, + since it's a stack-allocated temporary. + +2011-03-13 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Removed one case of DeprecatedPtr (ScopeChainIterator) + https://bugs.webkit.org/show_bug.cgi?id=56277 + + * runtime/ScopeChain.h: Direct pointer is fine for ScopeChainIterator, + since it's a stack-allocated temporary. + +2011-03-13 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + Bug 56273 - Add three operand forms to MacroAssember operations. + + Adding for X86(_64) for now, should be rolled out to other backends as necessary. + These may allow more efficient code generation in some cases, avoiding the need + for unnecessary register-register move instructions. + + * assembler/AbstractMacroAssembler.h: + (JSC::AbstractMacroAssembler::Jump::link): + (JSC::AbstractMacroAssembler::Jump::linkTo): + - marked these methods const. + (JSC::AbstractMacroAssembler::Jump::isSet): + - add a method to check whether a Jump object has been set to + reference an instruction, or is in a null, unset state. + * assembler/MacroAssemblerCodeRef.h: + (JSC::FunctionPtr::FunctionPtr): + - add non-explicit constructor, for FunctionPtr's to C/C++ functions. + * assembler/MacroAssemblerX86Common.h: + (JSC::MacroAssemblerX86Common::and32): + (JSC::MacroAssemblerX86Common::lshift32): + (JSC::MacroAssemblerX86Common::or32): + (JSC::MacroAssemblerX86Common::rshift32): + (JSC::MacroAssemblerX86Common::urshift32): + (JSC::MacroAssemblerX86Common::xor32): + (JSC::MacroAssemblerX86Common::moveDouble): + (JSC::MacroAssemblerX86Common::addDouble): + (JSC::MacroAssemblerX86Common::divDouble): + (JSC::MacroAssemblerX86Common::subDouble): + (JSC::MacroAssemblerX86Common::mulDouble): + (JSC::MacroAssemblerX86Common::branchTruncateDoubleToInt32): + (JSC::MacroAssemblerX86Common::branchTest32): + (JSC::MacroAssemblerX86Common::branchTest8): + (JSC::MacroAssemblerX86Common::branchAdd32): + (JSC::MacroAssemblerX86Common::branchMul32): + (JSC::MacroAssemblerX86Common::branchSub32): + - add three operand forms of these instructions. + * assembler/MacroAssemblerX86_64.h: + (JSC::MacroAssemblerX86_64::addDouble): + (JSC::MacroAssemblerX86_64::convertInt32ToDouble): + (JSC::MacroAssemblerX86_64::loadPtr): + (JSC::MacroAssemblerX86_64::branchTestPtr): + * assembler/X86Assembler.h: + (JSC::X86Assembler::JmpSrc::isSet): + - add a method to check whether a JmpSrc object has been set to + reference an instruction, or is in a null, unset state. + (JSC::X86Assembler::movsd_rr): + - added FP register-register move. + (JSC::X86Assembler::linkJump): + - Add an assert to check jumps aren't linked more than once. + * jit/JITInlineMethods.h: + (JSC::JIT::emitLoadInt32ToDouble): + - load integers to the FPU via regsiters on x86-64. + +2011-03-13 Gavin Barraclough <barraclough@apple.com> + + ARM build fix. + + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::load32): + +2011-03-13 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + Bug 56270 - The JIT 'friend's many classes in JSC; start unwinding this. + + The JIT need to 'friend' other classes in order to be able to calculate offsets + of various properties, or the absolute addresses of members within specific objects, + in order to JIT generate code that will access members within the class when run. + + Instead of using friends in these cases, switch to providing specific accessor + methods to provide this information. In the case of offsets, these can be static + functions, and in the case of pointers to members within a specific object these can + be const methods returning pointers to const values, to prevent clients from + modifying values otherwise encapsulated within classes. + + * bytecode/SamplingTool.h: + * interpreter/Register.h: + * interpreter/RegisterFile.h: + * runtime/JSArray.h: + * runtime/JSCell.h: + * runtime/JSTypeInfo.h: + * runtime/JSVariableObject.h: + * runtime/Structure.h: + * wtf/RefCounted.h: + - Change these classes to no longer friend the JIT, add accessors for member offsets. + * jit/JIT.cpp: + * jit/JITCall32_64.cpp: + * jit/JITInlineMethods.h: + * jit/JITOpcodes.cpp: + * jit/JITOpcodes32_64.cpp: + * jit/JITPropertyAccess.cpp: + * jit/JITPropertyAccess32_64.cpp: + - Change the JIT to use class accessors, rather than taking object ofsets directly. + * assembler/AbstractMacroAssembler.h: + * assembler/MacroAssemblerX86_64.h: + * assembler/X86Assembler.h: + - Since the accessors for objects members return const pointers to retain encapsulation, + methods generating code with absolute addresses must be able to handle const pointers + (the JIT doesn't write to these values, do dies treat the pointer to value as const + from within the C++ code of the JIT, if not at runtime!). + +2011-03-12 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r80919. + http://trac.webkit.org/changeset/80919 + https://bugs.webkit.org/show_bug.cgi?id=56251 + + all windows bots failed to compile this change (Requested by + loislo on #webkit). + + * JavaScriptCore.xcodeproj/project.pbxproj: + * bytecode/StructureStubInfo.cpp: + * interpreter/Register.h: + (JSC::Register::withInt): + (JSC::Register::withCallee): + (JSC::Register::operator=): + (JSC::Register::i): + (JSC::Register::activation): + (JSC::Register::function): + (JSC::Register::propertyNameIterator): + (JSC::Register::scopeChain): + * jit/JIT.h: + * jit/JITCall.cpp: + (JSC::JIT::compileOpCallInitializeCallFrame): + (JSC::JIT::compileOpCallVarargs): + (JSC::JIT::compileOpCall): + * jit/JITCall32_64.cpp: + (JSC::JIT::compileOpCallInitializeCallFrame): + (JSC::JIT::compileOpCallVarargs): + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpCallSlowCase): + * jit/JITInlineMethods.h: + (JSC::JIT::emitPutToCallFrameHeader): + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTINativeCall): + (JSC::JIT::emit_op_get_pnames): + (JSC::JIT::emit_op_next_pname): + (JSC::JIT::emit_op_load_varargs): + (JSC::JIT::emitSlow_op_load_varargs): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::privateCompileCTINativeCall): + (JSC::JIT::emit_op_get_pnames): + (JSC::JIT::emit_op_next_pname): + * jit/JSInterfaceJIT.h: + (JSC::JSInterfaceJIT::payloadFor): + * jit/SpecializedThunkJIT.h: + (JSC::SpecializedThunkJIT::returnJSValue): + (JSC::SpecializedThunkJIT::returnDouble): + (JSC::SpecializedThunkJIT::returnInt32): + (JSC::SpecializedThunkJIT::returnJSCell): + * runtime/ArgList.cpp: + * runtime/DateConversion.cpp: + * runtime/GCActivityCallbackCF.cpp: + * runtime/Identifier.cpp: + * runtime/JSActivation.h: + (JSC::asActivation): + * runtime/JSLock.cpp: + * runtime/JSNumberCell.cpp: + * runtime/JSObject.h: + * runtime/JSPropertyNameIterator.h: + * runtime/JSValue.h: + * runtime/JSZombie.cpp: + * runtime/MarkedBlock.cpp: + * runtime/MarkedSpace.cpp: + * runtime/PropertyNameArray.cpp: + * runtime/ScopeChain.h: + (JSC::ExecState::globalThisValue): + * wtf/DateMath.cpp: + +2011-03-11 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Ensure all values are correctly tagged in the registerfile + https://bugs.webkit.org/show_bug.cgi?id=56214 + + This patch makes sure that all JSCell pointers written to + the registerfile are correctly tagged as JSCells, and replaces + raw int usage with the immediate representation. + + For performance, register pressure, and general saneness reasons + I've added abstractions for reading and writing the tag + and payload of integer registers directly for the JSVALUE64 + encoding. + + * interpreter/Register.h: + (JSC::Register::withInt): + (JSC::Register::withCallee): + (JSC::Register::operator=): + (JSC::Register::i): + (JSC::Register::activation): + (JSC::Register::function): + (JSC::Register::propertyNameIterator): + (JSC::Register::scopeChain): + * jit/JIT.h: + * jit/JITCall.cpp: + (JSC::JIT::compileOpCallInitializeCallFrame): + (JSC::JIT::compileOpCallVarargs): + (JSC::JIT::compileOpCall): + * jit/JITCall32_64.cpp: + (JSC::JIT::compileOpCallInitializeCallFrame): + (JSC::JIT::compileOpCallVarargs): + (JSC::JIT::compileOpCall): + (JSC::JIT::compileOpCallSlowCase): + * jit/JITInlineMethods.h: + (JSC::JIT::emitPutToCallFrameHeader): + (JSC::JIT::emitPutCellToCallFrameHeader): + (JSC::JIT::emitPutIntToCallFrameHeader): + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTINativeCall): + (JSC::JIT::emit_op_get_pnames): + (JSC::JIT::emit_op_next_pname): + (JSC::JIT::emit_op_load_varargs): + (JSC::JIT::emitSlow_op_load_varargs): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::privateCompileCTINativeCall): + (JSC::JIT::emit_op_get_pnames): + (JSC::JIT::emit_op_next_pname): + * jit/JSInterfaceJIT.h: + (JSC::JSInterfaceJIT::intPayloadFor): + (JSC::JSInterfaceJIT::intTagFor): + * jit/SpecializedThunkJIT.h: + (JSC::SpecializedThunkJIT::returnJSValue): + (JSC::SpecializedThunkJIT::returnDouble): + (JSC::SpecializedThunkJIT::returnInt32): + (JSC::SpecializedThunkJIT::returnJSCell): + +2011-03-11 Dimitri Glazkov <dglazkov@chromium.org> + + Reviewed by Eric Seidel. + + Introduce project_dir variable and make paths a whole lot saner. Ok, a little bit saner. + https://bugs.webkit.org/show_bug.cgi?id=56231 + + * JavaScriptCore.gypi: Added project_dir variable. + * gyp/JavaScriptCore.gyp: Changed to use project_dir, rather than DEPTH/JavaScriptCore. + * gyp/generate-dtrace-header.sh: Changed to use project_dir. + +2011-03-11 Dimitri Glazkov <dglazkov@chromium.org> + + Reviewed by Adam Barth. + + Start using derived sources correctly and link minidom with JavaScriptCore gyp project. + https://bugs.webkit.org/show_bug.cgi?id=56217 + + * gyp/JavaScriptCore.gyp: Added derived source files and passing of shared directory + to the scripts. + * gyp/generate-derived-sources.sh: Changed to use passed directory. + * gyp/generate-dtrace-header.sh: Ditto. + +2011-03-11 Eric Carlson <eric.carlson@apple.com> + + Reviewed by Sam Weinig. + + <rdar://problem/8955589> Adopt AVFoundation media back end on Lion. + + No new tests, existing media tests cover this. + + * JavaScriptCore.exp: Export cancelCallOnMainThread + * wtf/Platform.h: Define WTF_USE_AVFOUNDATION. + +2011-03-11 Dimitri Glazkov <dglazkov@chromium.org> + + Reviewed by Adam Barth. + + Tweak dylib paths and add dtrace header generation action to JavaScriptCore gyp project. + https://bugs.webkit.org/show_bug.cgi?id=56207 + + * JavaScriptCore.gypi: Added Tracing.d to the sources. + * gyp/generate-dtrace-header.sh: Added. + * gyp/JavaScriptCore.gyp: Updated dylib paths (now the project can see them), + and added DTrace header generating step. + +2011-03-10 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Fix allocation of native function with a cached thunk + https://bugs.webkit.org/show_bug.cgi?id=56127 + + Fix this race condition found while fixing zombies. + + * collector/handles/HandleHeap.cpp: + (JSC::HandleHeap::clearWeakPointers): + * runtime/Heap.cpp: + (JSC::Heap::reset): + * runtime/JSFunction.cpp: + (JSC::JSFunction::JSFunction): + (JSC::JSFunction::markChildren): + * runtime/JSValue.h: + (JSC::JSValue::decode): + * runtime/JSZombie.cpp: + (JSC::JSZombie::leakedZombieStructure): + * runtime/JSZombie.h: + (JSC::JSZombie::createStructure): + * runtime/MarkedBlock.cpp: + +2011-03-10 Luiz Agostini <luiz.agostini@openbossa.org> + + Reviewed by Andreas Kling. + + [Qt] fast/workers/stress-js-execution.html is crashing on Qt bot (intermittently) + https://bugs.webkit.org/show_bug.cgi?id=33008 + + Defining WTF_USE_PTHREAD_BASED_QT=1 for platforms where QThread uses pthread internally. + Symbian is excluded because pthread_kill does not work on it. Mac is excluded because + it has its own ways to do JSC threading. + + Defining WTF_USE_PTHREADS inside MachineStackMarker.cpp if USE(PTHREAD_BASED_QT) is true. + + * runtime/MachineStackMarker.cpp: + * wtf/Platform.h: + +2011-03-10 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Bug 56077 - ES5 conformance issues with RegExp.prototype + + There are three issues causing test failures in sputnik. + + (1) lastIndex should be converted at the point it is used, not the point it is set (this is visible if valueOf is overridden). + (2) The 'length' property of the test/exec functions should be 1. + (3) If no input is specified, the input to test()/exec() is "undefined" (i.e. ToString(undefined)) - not RegExp.input. + + * runtime/RegExpObject.cpp: + (JSC::RegExpObject::markChildren): + - Added to mark lastIndex + (JSC::regExpObjectLastIndex): + (JSC::setRegExpObjectLastIndex): + - lastIndex is now stored as a JSValue. + (JSC::RegExpObject::match): + - Use accessor methods to get/set lastIndex, add fast case for isUInt32 (don't convert to double). + * runtime/RegExpObject.h: + (JSC::RegExpObject::setLastIndex): + (JSC::RegExpObject::setLastIndex): + - Set lastIndex, either from a size_t or a JSValue. + (JSC::RegExpObject::getLastIndex): + - Get lastIndex. + (JSC::RegExpObject::RegExpObjectData::RegExpObjectData): + - Initialize as a JSValue. + * runtime/RegExpPrototype.cpp: + (JSC::RegExpPrototype::RegExpPrototype): + - Add test/exec properties with length 1. + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncMatch): + (JSC::stringProtoFuncSearch): + - Do not read RegExp.input if none is provided. + * tests/mozilla/js1_2/regexp/RegExp_input.js: + * tests/mozilla/js1_2/regexp/RegExp_input_as_array.js: + - Update these tests (they relied on non-ES5 behaviour). + +2011-03-10 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Rolled back in 80277 and 80280 with event handler layout test failures fixed. + https://bugs.webkit.org/show_bug.cgi?id=55653 + + The failures were caused by a last minute typo: assigning to currentEvent + instead of m_currentEvent. + + * JavaScriptCore.exp: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.xcodeproj/project.pbxproj: + * bytecompiler/BytecodeGenerator.cpp: + * jit/JITOpcodes.cpp: + * jit/JITOpcodes32_64.cpp: + * runtime/Arguments.h: + * runtime/JSActivation.cpp: + * runtime/JSActivation.h: + * runtime/JSCell.h: + * runtime/JSGlobalObject.cpp: + * runtime/JSGlobalObject.h: + * runtime/JSObject.cpp: + * runtime/JSStaticScopeObject.cpp: + * runtime/JSStaticScopeObject.h: + * runtime/JSVariableObject.h: + * runtime/MarkedSpace.cpp: + * runtime/MarkedSpace.h: + +2011-03-09 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + jquery/manipulation.html fails after r80598 + https://bugs.webkit.org/show_bug.cgi?id=56019 + + When linking a call, codeblock now takes ownership of the linked function + This removes the need for unlinking, and thus the incorrectness that was + showing up in these tests. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::~CodeBlock): + (JSC::CodeBlock::markAggregate): + * bytecode/CodeBlock.h: + (JSC::CallLinkInfo::CallLinkInfo): + (JSC::CallLinkInfo::setUnlinked): + (JSC::CodeBlock::addCaller): + * jit/JIT.cpp: + (JSC::JIT::privateCompile): + (JSC::JIT::linkCall): + (JSC::JIT::linkConstruct): + * jit/JIT.h: + * runtime/Executable.cpp: + * runtime/Executable.h: + +2011-03-09 Daniel Bates <dbates@rim.com> + + Attempt to fix the WinCE build after changeset 80684 <http://trac.webkit.org/changeset/80684> + (Bug #56041<https://bugs.webkit.org/show_bug.cgi?id=56041>). + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): Substitute variable callFrame for exec in call to createSyntaxError(). + +2011-03-09 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + Bug 56041 - RexExp constructor should only accept flags "gim" + Fix for issues introduced in r80667. + + Invalid flags to a RegExp literal are a late syntax error! + + * bytecode/CodeBlock.h: + (JSC::CodeBlock::addRegExp): + - Pass a PassRefPtr<RegExp> + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::addRegExp): + (JSC::BytecodeGenerator::emitNewRegExp): + * bytecompiler/BytecodeGenerator.h: + - Pass a PassRefPtr<RegExp> + * bytecompiler/NodesCodegen.cpp: + (JSC::RegExpNode::emitBytecode): + - Should not be ASSERTing that the flags are valid - this is a late(er) error. + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + - Need to check for error from RegExp constructor. + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + - Need to check for error from RegExp constructor. + * runtime/RegExp.h: + (JSC::RegExp::isValid): + - Make isValid check that the regexp was created with valid flags. + * runtime/RegExpKey.h: + - Since we'll not create RegExp objects with invalid flags, separate out the deleted value. + +2011-03-09 Gavin Barraclough <barraclough@apple.com> + + Windows build fix part 2. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2011-03-09 Gavin Barraclough <barraclough@apple.com> + + Windows build fix part 1. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2011-03-09 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Darin Adler. + + Bug 56041 - RexExp constructor should only accept flags "gim" + We also should be passing the flags around as a bitfield rather than a string, + and should not have redundant, incompatible code for converting the string to a bitfield! + + * JavaScriptCore.exp: + * bytecompiler/NodesCodegen.cpp: + (JSC::RegExpNode::emitBytecode): + - Need to parse flags string to enum. + * runtime/RegExp.cpp: + (JSC::regExpFlags): + (JSC::RegExp::RegExp): + (JSC::RegExp::create): + - Add method to parse flags string to enum, change constructor/create args to take enum. + * runtime/RegExp.h: + (JSC::RegExp::global): + (JSC::RegExp::ignoreCase): + (JSC::RegExp::multiline): + - Change to use new enum values. + * runtime/RegExpCache.cpp: + (JSC::RegExpCache::lookupOrCreate): + (JSC::RegExpCache::create): + * runtime/RegExpCache.h: + - Changed to use regExpFlags enum instead of int/const UString&. + * runtime/RegExpConstructor.cpp: + (JSC::constructRegExp): + - Add use new enum parsing, check for error. + * runtime/RegExpKey.h: + (JSC::RegExpKey::RegExpKey): + * runtime/RegExpPrototype.cpp: + (JSC::RegExpPrototype::RegExpPrototype): + - Pass NoFlags value instead of empty string. + (JSC::regExpProtoFuncCompile): + - Add use new enum parsing, check for error. + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncMatch): + (JSC::stringProtoFuncSearch): + - Pass NoFlags value instead of empty string. + +2011-03-08 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig + + Bug 55994 - Functions on Array.prototype should check length first. + These methods are designed to work on generic objects too, and if 'length' + is a getter that throws an exception, ensure this is correctly thrown + (even if other exceptions would be thrown, too). + + Make the length check the first thing we do. + This change shows a progression on SunSpider on my machine, but this is likely bogus. + + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToString): + (JSC::arrayProtoFuncToLocaleString): + (JSC::arrayProtoFuncJoin): + (JSC::arrayProtoFuncPop): + (JSC::arrayProtoFuncPush): + (JSC::arrayProtoFuncReverse): + (JSC::arrayProtoFuncShift): + (JSC::arrayProtoFuncSlice): + (JSC::arrayProtoFuncSort): + (JSC::arrayProtoFuncSplice): + (JSC::arrayProtoFuncUnShift): + (JSC::arrayProtoFuncFilter): + (JSC::arrayProtoFuncMap): + (JSC::arrayProtoFuncEvery): + (JSC::arrayProtoFuncForEach): + (JSC::arrayProtoFuncSome): + (JSC::arrayProtoFuncReduce): + (JSC::arrayProtoFuncReduceRight): + (JSC::arrayProtoFuncIndexOf): + (JSC::arrayProtoFuncLastIndexOf): + +2011-03-07 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Make CodeBlock GC write barrier safe + https://bugs.webkit.org/show_bug.cgi?id=55910 + + In order to make CodeBlock WriteBarrier safe it was necessary + to make it have a single GC owner, and for that reason I have + made ExecutableBase a GC allocated object. This required + updating their creation routines as well as all sites that hold + a reference to them. GC objects that held Executable's have been + converted to WriteBarriers, and all other sites now use Global<>. + + As an added benefit this gets rid of JSGlobalData's list of + GlobalCodeBlocks. + + Perf testing shows a 0.5% progression on v8, vs. a 0.3% regression + on SunSpider. Given none of the tests that show regressions + demonstrate a regression on their own, and sampling shows up nothing. + I suspect we're just getting one or two additional gc passes at + the end of the run. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + (JSC::CodeBlock::CodeBlock): + (JSC::EvalCodeCache::markAggregate): + (JSC::CodeBlock::markAggregate): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::ownerExecutable): + (JSC::CodeBlock::addConstant): + (JSC::CodeBlock::constantRegister): + (JSC::CodeBlock::getConstant): + (JSC::CodeBlock::addFunctionDecl): + (JSC::CodeBlock::addFunctionExpr): + (JSC::GlobalCodeBlock::GlobalCodeBlock): + (JSC::ExecState::r): + * bytecode/EvalCodeCache.h: + (JSC::EvalCodeCache::get): + * bytecode/SamplingTool.h: + (JSC::ScriptSampleRecord::ScriptSampleRecord): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::addConstantValue): + (JSC::BytecodeGenerator::emitEqualityOp): + * bytecompiler/BytecodeGenerator.h: + (JSC::BytecodeGenerator::makeFunction): + * debugger/Debugger.cpp: + (JSC::evaluateInGlobalCallFrame): + * debugger/DebuggerCallFrame.cpp: + (JSC::DebuggerCallFrame::evaluate): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::callEval): + * jit/JITInlineMethods.h: + (JSC::JIT::emitLoadDouble): + (JSC::JIT::emitLoadInt32ToDouble): + * jit/JITStubs.cpp: + (JSC::JITThunks::JITThunks): + (JSC::JITThunks::hostFunctionStub): + (JSC::JITThunks::clearHostFunctionStubs): + * jit/JITStubs.h: + * runtime/Completion.cpp: + (JSC::checkSyntax): + (JSC::evaluate): + * runtime/Executable.cpp: + (JSC::EvalExecutable::EvalExecutable): + (JSC::ProgramExecutable::ProgramExecutable): + (JSC::FunctionExecutable::FunctionExecutable): + (JSC::FunctionExecutable::~FunctionExecutable): + (JSC::EvalExecutable::markChildren): + (JSC::ProgramExecutable::markChildren): + (JSC::FunctionExecutable::markChildren): + (JSC::FunctionExecutable::fromGlobalCode): + * runtime/Executable.h: + (JSC::ExecutableBase::ExecutableBase): + (JSC::ExecutableBase::createStructure): + (JSC::NativeExecutable::create): + (JSC::NativeExecutable::NativeExecutable): + (JSC::VPtrHackExecutable::VPtrHackExecutable): + (JSC::ScriptExecutable::ScriptExecutable): + (JSC::EvalExecutable::create): + (JSC::EvalExecutable::createStructure): + (JSC::ProgramExecutable::create): + (JSC::ProgramExecutable::createStructure): + (JSC::FunctionExecutable::create): + (JSC::FunctionExecutable::createStructure): + * runtime/FunctionConstructor.cpp: + (JSC::constructFunction): + * runtime/Heap.cpp: + (JSC::Heap::destroy): + (JSC::Heap::markRoots): + * runtime/Heap.h: + * runtime/JSActivation.cpp: + (JSC::JSActivation::JSActivation): + (JSC::JSActivation::markChildren): + * runtime/JSActivation.h: + (JSC::JSActivation::JSActivationData::JSActivationData): + * runtime/JSCell.h: + * runtime/JSFunction.cpp: + (JSC::JSFunction::JSFunction): + (JSC::JSFunction::~JSFunction): + (JSC::JSFunction::markChildren): + * runtime/JSFunction.h: + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::storeVPtrs): + (JSC::JSGlobalData::JSGlobalData): + (JSC::JSGlobalData::getHostFunction): + * runtime/JSGlobalData.h: + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::globalFuncEval): + * runtime/JSObject.cpp: + * runtime/JSStaticScopeObject.cpp: + (JSC::JSStaticScopeObject::markChildren): + * runtime/JSStaticScopeObject.h: + (JSC::JSStaticScopeObject::JSStaticScopeObjectData::JSStaticScopeObjectData): + (JSC::JSStaticScopeObject::JSStaticScopeObject): + * runtime/JSZombie.cpp: + (JSC::JSZombie::leakedZombieStructure): + * runtime/JSZombie.h: + (JSC::JSZombie::createStructure): + * runtime/MarkedSpace.h: + +2011-03-07 Andy Estes <aestes@apple.com> + + Reviewed by Dan Bernstein. + + REGRESSION (r79060): Timestamp is missing from tweets in twitter. + https://bugs.webkit.org/show_bug.cgi?id=55228 + + A change to the date parser to handle the case where the year is + specified before the time zone inadvertently started accepting strings + such as '+0000' as valid years. Those strings actually represent time + zones in an offset of hours and minutes from UTC, not years. + + * wtf/DateMath.cpp: + (WTF::parseDateFromNullTerminatedCharacters): If the current character + in dateString is '+' or '-', do not try to parse the next token as a + year. + 2011-03-06 Yuta Kitamura <yutak@chromium.org> Reviewed by Kent Tamura. diff --git a/Source/JavaScriptCore/Configurations/Base.xcconfig b/Source/JavaScriptCore/Configurations/Base.xcconfig index 8d91d70..12d0efd 100644 --- a/Source/JavaScriptCore/Configurations/Base.xcconfig +++ b/Source/JavaScriptCore/Configurations/Base.xcconfig @@ -25,7 +25,6 @@ DEBUG_INFORMATION_FORMAT = dwarf; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DEBUGGING_SYMBOLS = default; GCC_DYNAMIC_NO_PIC = NO; -GCC_ENABLE_CPP_EXCEPTIONS = NO; GCC_ENABLE_CPP_RTTI = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_ENABLE_OBJC_GC = $(GCC_ENABLE_OBJC_GC_$(REAL_PLATFORM_NAME)); @@ -118,12 +117,23 @@ TARGET_GCC_VERSION_macosx_1050_ = $(TARGET_GCC_VERSION_macosx_1050_$(XCODE_VERSI TARGET_GCC_VERSION_macosx_1050_0310 = GCC_42; TARGET_GCC_VERSION_macosx_1050_0320 = GCC_42; TARGET_GCC_VERSION_macosx_1060 = GCC_42; -TARGET_GCC_VERSION_macosx_1070 = LLVM_GCC_42; +TARGET_GCC_VERSION_macosx_1070 = $(TARGET_GCC_VERSION_macosx_1070_$(CONFIGURATION)); +TARGET_GCC_VERSION_macosx_1070_Debug = LLVM_COMPILER; +TARGET_GCC_VERSION_macosx_1070_Release = LLVM_GCC_42; +TARGET_GCC_VERSION_macosx_1070_Production = LLVM_GCC_42; GCC_VERSION = $(GCC_VERSION_$(TARGET_GCC_VERSION)); GCC_VERSION_GCC_40 = 4.0; GCC_VERSION_GCC_42 = 4.2; GCC_VERSION_LLVM_GCC_42 = com.apple.compilers.llvmgcc42; +GCC_VERSION_LLVM_COMPILER = com.apple.compilers.llvm.clang.1_0; + +// FIXME: Disable C++ exceptions in the LLVM Compiler once it supports enabling Obj-C exceptions without C++ exceptions. +GCC_ENABLE_CPP_EXCEPTIONS = $(GCC_ENABLE_CPP_EXCEPTIONS_$(TARGET_GCC_VERSION)); +GCC_ENABLE_CPP_EXCEPTIONS_GCC_40 = NO; +GCC_ENABLE_CPP_EXCEPTIONS_GCC_42 = NO; +GCC_ENABLE_CPP_EXCEPTIONS_LLVM_GCC = NO; +GCC_ENABLE_CPP_EXCEPTIONS_LLVM_COMPILER = YES; // If the target Mac OS X version does not match the current Mac OS X version then we'll want to build using the target version's SDK. SDKROOT = $(SDKROOT_$(MAC_OS_X_VERSION_MAJOR)_$(TARGET_MAC_OS_X_VERSION_MAJOR)); diff --git a/Source/JavaScriptCore/Configurations/Version.xcconfig b/Source/JavaScriptCore/Configurations/Version.xcconfig index ae9167c..59988e3 100644 --- a/Source/JavaScriptCore/Configurations/Version.xcconfig +++ b/Source/JavaScriptCore/Configurations/Version.xcconfig @@ -22,7 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAJOR_VERSION = 534; -MINOR_VERSION = 24; +MINOR_VERSION = 27; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/Source/JavaScriptCore/DerivedSources.make b/Source/JavaScriptCore/DerivedSources.make index 8abb17c..9a8c2cc 100644 --- a/Source/JavaScriptCore/DerivedSources.make +++ b/Source/JavaScriptCore/DerivedSources.make @@ -84,7 +84,6 @@ HeaderDetection.h : DerivedSources.make /System/Library/CoreServices/SystemVersi rm -f $@ echo "/* This is a generated file. Do not edit. */" > $@ if [ -f $(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/pthread_machdep.h ]; then echo "#define HAVE_PTHREAD_MACHDEP_H 1" >> $@; else echo >> $@; fi - if [ -f $(SDKROOT)/System/Library/Frameworks/AppKit.framework/PrivateHeaders/NSScrollerImpPair_Private.h ]; then echo "#define USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER 1" >> $@; else echo >> $@; fi else diff --git a/Source/JavaScriptCore/GNUmakefile.am b/Source/JavaScriptCore/GNUmakefile.am index 977cb18..31e70a0 100644 --- a/Source/JavaScriptCore/GNUmakefile.am +++ b/Source/JavaScriptCore/GNUmakefile.am @@ -115,6 +115,10 @@ javascriptcore_sources += \ Source/JavaScriptCore/collector/handles/Handle.h \ Source/JavaScriptCore/collector/handles/HandleHeap.cpp \ Source/JavaScriptCore/collector/handles/HandleHeap.h \ + Source/JavaScriptCore/collector/handles/HandleStack.cpp \ + Source/JavaScriptCore/collector/handles/HandleStack.h \ + Source/JavaScriptCore/collector/handles/Local.h \ + Source/JavaScriptCore/collector/handles/LocalScope.h \ Source/JavaScriptCore/config.h \ Source/JavaScriptCore/debugger/DebuggerActivation.cpp \ Source/JavaScriptCore/debugger/DebuggerActivation.h \ @@ -468,6 +472,7 @@ javascriptcore_sources += \ Source/JavaScriptCore/wtf/HashTable.cpp \ Source/JavaScriptCore/wtf/HashTable.h \ Source/JavaScriptCore/wtf/HashTraits.h \ + Source/JavaScriptCore/wtf/HexNumber.h \ Source/JavaScriptCore/wtf/ListHashSet.h \ Source/JavaScriptCore/wtf/ListRefPtr.h \ Source/JavaScriptCore/wtf/Locker.h \ @@ -549,7 +554,7 @@ javascriptcore_sources += \ Source/JavaScriptCore/wtf/Threading.h \ Source/JavaScriptCore/wtf/ThreadingPrimitives.h \ Source/JavaScriptCore/wtf/ThreadingPthreads.cpp \ - Source/JavaScriptCore/wtf/ThreadSafeShared.h \ + Source/JavaScriptCore/wtf/ThreadSafeRefCounted.h \ Source/JavaScriptCore/wtf/ThreadSpecific.h \ Source/JavaScriptCore/wtf/TypeTraits.cpp \ Source/JavaScriptCore/wtf/TypeTraits.h \ diff --git a/Source/JavaScriptCore/JavaScriptCore.exp b/Source/JavaScriptCore/JavaScriptCore.exp index 914c2ac..e2647d1 100644 --- a/Source/JavaScriptCore/JavaScriptCore.exp +++ b/Source/JavaScriptCore/JavaScriptCore.exp @@ -1,4 +1,3 @@ -__ZN3JSC22objectConstructorTableE _JSCheckScriptSyntax _JSClassCreate _JSClassRelease @@ -114,15 +113,15 @@ __ZN3JSC10JSFunction6s_infoE __ZN3JSC10throwErrorEPNS_9ExecStateENS_7JSValueE __ZN3JSC10throwErrorEPNS_9ExecStateEPNS_8JSObjectE __ZN3JSC11JSByteArray13s_defaultInfoE -__ZN3JSC11JSByteArray15createStructureENS_7JSValueEPKNS_9ClassInfoE +__ZN3JSC11JSByteArray15createStructureERNS_12JSGlobalDataENS_7JSValueEPKNS_9ClassInfoE __ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS3_9ByteArrayE __ZN3JSC11MarkedSpace21allocateFromSizeClassERNS0_9SizeClassE __ZN3JSC11ParserArena5resetEv __ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE __ZN3JSC11createErrorEPNS_9ExecStateERKNS_7UStringE +__ZN3JSC11regExpFlagsERKNS_7UStringE __ZN3JSC12DateInstance6s_infoE __ZN3JSC12DateInstanceC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEd -__ZN3JSC12DateInstanceC1EPNS_9ExecStateEd __ZN3JSC12JSGlobalData10ClientDataD2Ev __ZN3JSC12JSGlobalData11jsArrayVPtrE __ZN3JSC12JSGlobalData12createLeakedENS_15ThreadStackTypeE @@ -159,11 +158,11 @@ __ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSO __ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj __ZN3JSC14JSGlobalObject12markChildrenERNS_9MarkStackE __ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj -__ZN3JSC14JSGlobalObject25destroyJSGlobalObjectDataEPv __ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE __ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE __ZN3JSC14JSGlobalObjectD2Ev __ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE +__ZN3JSC14MachineThreads16addCurrentThreadEv __ZN3JSC14SamplingThread4stopEv __ZN3JSC14SamplingThread5startEj __ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE @@ -182,10 +181,9 @@ __ZN3JSC16createRangeErrorEPNS_9ExecStateERKNS_7UStringE __ZN3JSC16throwSyntaxErrorEPNS_9ExecStateE __ZN3JSC17BytecodeGenerator21setDumpsGeneratedCodeEb __ZN3JSC17PropertyNameArray3addEPN3WTF10StringImplE -__ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi +__ZN3JSC17constructFunctionEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi __ZN3JSC17createSyntaxErrorEPNS_9ExecStateERKNS_7UStringE __ZN3JSC18DebuggerActivationC1ERNS_12JSGlobalDataEPNS_8JSObjectE -__ZN3JSC18MachineStackMarker14registerThreadEv __ZN3JSC18PropertyDescriptor11setWritableEb __ZN3JSC18PropertyDescriptor12setUndefinedEv __ZN3JSC18PropertyDescriptor13setDescriptorENS_7JSValueEj @@ -201,13 +199,13 @@ __ZN3JSC19initializeThreadingEv __ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE __ZN3JSC20createReferenceErrorEPNS_9ExecStateERKNS_7UStringE __ZN3JSC22globalMemoryStatisticsEv +__ZN3JSC22objectConstructorTableE __ZN3JSC23AbstractSamplingCounter4dumpEv __ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateE __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE -__ZN3JSC24DynamicGlobalObjectScopeC1EPNS_9ExecStateEPNS_14JSGlobalObjectE +__ZN3JSC24DynamicGlobalObjectScopeC1ERNS_12JSGlobalDataEPNS_14JSGlobalObjectE __ZN3JSC24JSObjectWithGlobalObjectC2EPNS_14JSGlobalObjectEN3WTF17NonNullPassRefPtrINS_9StructureEEE __ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE -__ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE __ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObjectE __ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE __ZN3JSC3NaNE @@ -248,7 +246,7 @@ __ZN3JSC6JSLock4lockENS_14JSLockBehaviorE __ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE __ZN3JSC6JSLock9lockCountEv __ZN3JSC6JSLockC1EPNS_9ExecStateE -__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringES5_ +__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringENS_11RegExpFlagsE __ZN3JSC6RegExpD1Ev __ZN3JSC7JSArray12markChildrenERNS_9MarkStackE __ZN3JSC7JSArray15setSubclassDataEPv @@ -287,7 +285,6 @@ __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj __ZN3JSC8JSObject15unwrappedObjectEv __ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE -__ZN3JSC8JSObject17createInheritorIDEv __ZN3JSC8JSObject17defineOwnPropertyEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorEb __ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_10JSFunctionEj __ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_16InternalFunctionEj @@ -387,6 +384,7 @@ __ZN3WTF12createThreadEPFPvS0_ES0_PKc __ZN3WTF12detachThreadEj __ZN3WTF12isMainThreadEv __ZN3WTF12randomNumberEv +__ZN3WTF13StringBuilder15reserveCapacityEj __ZN3WTF13StringBuilder11reifyStringEv __ZN3WTF13StringBuilder11shrinkToFitEv __ZN3WTF13StringBuilder6appendEPKcj @@ -431,6 +429,7 @@ __ZN3WTF21RefCountedLeakCounter9incrementEv __ZN3WTF21RefCountedLeakCounterC1EPKc __ZN3WTF21RefCountedLeakCounterD1Ev __ZN3WTF21charactersToIntStrictEPKtmPbi +__ZN3WTF22cancelCallOnMainThreadEPFvPvES0_ __ZN3WTF22charactersToUIntStrictEPKtmPbi __ZN3WTF23callOnMainThreadAndWaitEPFvPvES0_ __ZN3WTF23dayInMonthFromDayInYearEib @@ -446,10 +445,10 @@ __ZN3WTF39initializeMainThreadToProcessMainThreadEv __ZN3WTF3MD58addBytesEPKhm __ZN3WTF3MD58checksumERNS_6VectorIhLm16EEE __ZN3WTF3MD5C1Ev -__ZN3WTF4dtoaEPcdRbRiRj __ZN3WTF4SHA111computeHashERNS_6VectorIhLm20EEE __ZN3WTF4SHA18addBytesEPKhm __ZN3WTF4SHA1C1Ev +__ZN3WTF4dtoaEPcdRbRiRj __ZN3WTF5Mutex4lockEv __ZN3WTF5Mutex6unlockEv __ZN3WTF5Mutex7tryLockEv @@ -535,7 +534,7 @@ __ZNK3JSC6JSCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE __ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE __ZNK3JSC6JSCell14isGetterSetterEv __ZNK3JSC6JSCell8toNumberEPNS_9ExecStateE -__ZNK3JSC6JSCell8toObjectEPNS_9ExecStateE +__ZNK3JSC6JSCell8toObjectEPNS_9ExecStateEPNS_14JSGlobalObjectE __ZNK3JSC6JSCell8toStringEPNS_9ExecStateE __ZNK3JSC6JSCell9getStringEPNS_9ExecStateE __ZNK3JSC6JSCell9getStringEPNS_9ExecStateERNS_7UStringE @@ -543,7 +542,7 @@ __ZNK3JSC6JSCell9getUInt32ERj __ZNK3JSC6JSCell9toBooleanEPNS_9ExecStateE __ZNK3JSC7ArgList8getSliceEiRS0_ __ZNK3JSC7JSArray12subclassDataEv -__ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateE +__ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateEPNS_14JSGlobalObjectE __ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE __ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE __ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE @@ -556,7 +555,7 @@ __ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE __ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE __ZNK3JSC8JSObject18toStrictThisObjectEPNS_9ExecStateE __ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE -__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE +__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateEPNS_14JSGlobalObjectE __ZNK3JSC8JSObject8toStringEPNS_9ExecStateE __ZNK3JSC8JSObject9classNameEv __ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE diff --git a/Source/JavaScriptCore/JavaScriptCore.gypi b/Source/JavaScriptCore/JavaScriptCore.gypi index 292473c..cb93a29 100644 --- a/Source/JavaScriptCore/JavaScriptCore.gypi +++ b/Source/JavaScriptCore/JavaScriptCore.gypi @@ -1,5 +1,6 @@ { 'variables': { + 'project_dir': ['.'], # These headers are part of JavaScriptCore's public API in the Apple Mac build. 'javascriptcore_publicheader_files': [ 'API/JSBase.h', @@ -29,6 +30,9 @@ 'collector/handles/Global.h', 'collector/handles/Handle.h', 'collector/handles/HandleHeap.h', + 'collector/handles/HandleStack.h', + 'collector/handles/Local.h', + 'collector/handles/LocalScope.h', 'config.h', 'debugger/Debugger.h', 'debugger/DebuggerActivation.h', @@ -64,6 +68,7 @@ 'runtime/ExceptionHelpers.h', 'runtime/FunctionConstructor.h', 'runtime/FunctionPrototype.h', + 'runtime/GCActivityCallback.h', 'runtime/Heap.h', 'runtime/Identifier.h', 'runtime/InitializeThreading.h', @@ -105,7 +110,9 @@ 'runtime/Protect.h', 'runtime/PutPropertySlot.h', 'runtime/RegExp.h', + 'runtime/RegExpKey.h', 'runtime/RegExpCache.h', + 'runtime/RegExpObject.h', 'runtime/RopeImpl.h', 'runtime/ScopeChain.h', 'runtime/SmallStrings.h', @@ -157,6 +164,7 @@ 'wtf/HashSet.h', 'wtf/HashTable.h', 'wtf/HashTraits.h', + 'wtf/HexNumber.h', 'wtf/ListHashSet.h', 'wtf/ListRefPtr.h', 'wtf/Locker.h', @@ -195,7 +203,7 @@ 'wtf/StdLibExtras.h', 'wtf/StringExtras.h', 'wtf/StringHasher.h', - 'wtf/ThreadSafeShared.h', + 'wtf/ThreadSafeRefCounted.h', 'wtf/ThreadSpecific.h', 'wtf/Threading.h', 'wtf/ThreadingPrimitives.h', @@ -303,9 +311,29 @@ 'bytecompiler/NodesCodegen.cpp', 'bytecompiler/RegisterID.h', 'collector/handles/HandleHeap.cpp', + 'collector/handles/HandleStack.cpp', 'debugger/Debugger.cpp', 'debugger/DebuggerActivation.cpp', 'debugger/DebuggerCallFrame.cpp', + 'dfg/DFGAliasTracker.h', + 'dfg/DFGByteCodeParser.cpp', + 'dfg/DFGByteCodeParser.h', + 'dfg/DFGGenerationInfo.h', + 'dfg/DFGGraph.cpp', + 'dfg/DFGGraph.h', + 'dfg/DFGJITCodeGenerator.cpp', + 'dfg/DFGJITCodeGenerator.h', + 'dfg/DFGJITCompiler.cpp', + 'dfg/DFGJITCompiler.h', + 'dfg/DFGNode.h', + 'dfg/DFGNonSpeculativeJIT.cpp', + 'dfg/DFGNonSpeculativeJIT.h', + 'dfg/DFGOperations.cpp', + 'dfg/DFGOperations.h', + 'dfg/DFGRegisterBank.h', + 'dfg/DFGScoreBoard.h', + 'dfg/DFGSpeculativeJIT.cpp', + 'dfg/DFGSpeculativeJIT.h', 'icu/unicode/parseerr.h', 'icu/unicode/platform.h', 'icu/unicode/putil.h', @@ -351,6 +379,10 @@ 'jit/JSInterfaceJIT.h', 'jit/SpecializedThunkJIT.h', 'jit/ThunkGenerators.cpp', + 'os-win32/WinMain.cpp', + 'os-win32/inttypes.h', + 'os-win32/stdbool.h', + 'os-win32/stdint.h', 'parser/ASTBuilder.h', 'parser/JSParser.cpp', 'parser/JSParser.h', @@ -447,7 +479,6 @@ 'runtime/FunctionConstructor.cpp', 'runtime/FunctionPrototype.cpp', 'runtime/GCActivityCallback.cpp', - 'runtime/GCActivityCallback.h', 'runtime/GCActivityCallbackCF.cpp', 'runtime/GetterSetter.cpp', 'runtime/GetterSetter.h', @@ -517,10 +548,8 @@ 'runtime/RegExpCache.cpp', 'runtime/RegExpConstructor.cpp', 'runtime/RegExpConstructor.h', - 'runtime/RegExpKey.h', 'runtime/RegExpMatchesArray.h', 'runtime/RegExpObject.cpp', - 'runtime/RegExpObject.h', 'runtime/RegExpPrototype.cpp', 'runtime/RegExpPrototype.h', 'runtime/RopeImpl.cpp', @@ -538,6 +567,7 @@ 'runtime/Structure.cpp', 'runtime/StructureChain.cpp', 'runtime/TimeoutChecker.cpp', + 'runtime/Tracing.d', 'runtime/Tracing.h', 'runtime/UString.cpp', 'runtime/UStringConcatenate.h', @@ -564,9 +594,9 @@ 'wtf/RandomNumber.cpp', 'wtf/RandomNumberSeed.h', 'wtf/RefCountedLeakCounter.cpp', - 'wtf/SegmentedVector.h', 'wtf/SHA1.cpp', 'wtf/SHA1.h', + 'wtf/SegmentedVector.h', 'wtf/SizeLimits.cpp', 'wtf/StackBounds.cpp', 'wtf/StringExtras.cpp', @@ -656,13 +686,20 @@ 'yarr/YarrSyntaxChecker.cpp', 'yarr/YarrSyntaxChecker.h', ], - # These files are separate from javascriptcore_files so we can use a - # header map in the Apple Mac Xcode build. - 'os_win32_files': [ - 'os-win32/WinMain.cpp', - 'os-win32/inttypes.h', - 'os-win32/stdbool.h', - 'os-win32/stdint.h', + 'javascriptcore_derived_source_files': [ + '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/ArrayPrototype.lut.h', + '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/DatePrototype.lut.h', + '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/HeaderDetection.h', + '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/JSONObject.lut.h', + '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/Lexer.lut.h', + '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/MathObject.lut.h', + '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/NumberConstructor.lut.h', + '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/RegExpConstructor.lut.h', + '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/RegExpJitTables.h', + '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/RegExpObject.lut.h', + '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/StringPrototype.lut.h', + '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/TracingDtrace.h', + '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/ObjectConstructor.lut.h', ], 'minidom_files': [ 'API/tests/JSNode.c', diff --git a/Source/JavaScriptCore/JavaScriptCore.pri b/Source/JavaScriptCore/JavaScriptCore.pri index 391c74f..941a708 100644 --- a/Source/JavaScriptCore/JavaScriptCore.pri +++ b/Source/JavaScriptCore/JavaScriptCore.pri @@ -26,6 +26,7 @@ JAVASCRIPTCORE_INCLUDEPATH = \ $$PWD/bytecode \ $$PWD/bytecompiler \ $$PWD/collector/handles \ + $$PWD/dfg \ $$PWD/debugger \ $$PWD/interpreter \ $$PWD/jit \ diff --git a/Source/JavaScriptCore/JavaScriptCore.pro b/Source/JavaScriptCore/JavaScriptCore.pro index e41f04d..80ad3e8 100644 --- a/Source/JavaScriptCore/JavaScriptCore.pro +++ b/Source/JavaScriptCore/JavaScriptCore.pro @@ -69,10 +69,18 @@ SOURCES += \ bytecode/StructureStubInfo.cpp \ bytecompiler/BytecodeGenerator.cpp \ bytecompiler/NodesCodegen.cpp \ + collector/handles/HandleHeap.cpp \ + collector/handles/HandleStack.cpp \ debugger/DebuggerActivation.cpp \ debugger/DebuggerCallFrame.cpp \ debugger/Debugger.cpp \ - collector/handles/HandleHeap.cpp \ + dfg/DFGByteCodeParser.cpp \ + dfg/DFGGraph.cpp \ + dfg/DFGJITCodeGenerator.cpp \ + dfg/DFGJITCompiler.cpp \ + dfg/DFGNonSpeculativeJIT.cpp \ + dfg/DFGOperations.cpp \ + dfg/DFGSpeculativeJIT.cpp \ interpreter/CallFrame.cpp \ interpreter/Interpreter.cpp \ interpreter/RegisterFile.cpp \ diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make index 68075f9..b5461e4 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make @@ -5,7 +5,6 @@ BUILDSTYLE=Release_PGO !ENDIF install: - set PRODUCTION=1 set WebKitLibrariesDir=$(SRCROOT)\AppleInternal set WebKitOutputDir=$(OBJROOT) set ConfigurationBuildDir=$(OBJROOT)\$(BUILDSTYLE) diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln index a4832ed..0b610e2 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln @@ -22,7 +22,7 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_All|Win32 = Debug_All|Win32 Debug|Win32 = Debug|Win32 - Release_LTCG|Win32 = Release_LTCG|Win32 + Production|Win32 = Production|Win32 Release_PGO_Optimize|Win32 = Release_PGO_Optimize|Win32 Release_PGO|Win32 = Release_PGO|Win32 Release|Win32 = Release|Win32 @@ -32,8 +32,8 @@ Global {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Debug_All|Win32.Build.0 = Debug_All|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Debug|Win32.ActiveCfg = Debug|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Debug|Win32.Build.0 = Debug|Win32 - {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_LTCG|Win32.ActiveCfg = Release_LTCG|Win32 - {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_LTCG|Win32.Build.0 = Release_LTCG|Win32 + {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Production|Win32.ActiveCfg = Production|Win32 + {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Production|Win32.Build.0 = Production|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_PGO_Optimize|Win32.ActiveCfg = Release_PGO_Optimize|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_PGO_Optimize|Win32.Build.0 = Release_PGO_Optimize|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_PGO|Win32.ActiveCfg = Release_PGO|Win32 @@ -44,8 +44,8 @@ Global {C59E5129-B453-49B7-A52B-1E104715F76E}.Debug_All|Win32.Build.0 = Debug_All|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Debug|Win32.ActiveCfg = Debug|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Debug|Win32.Build.0 = Debug|Win32 - {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_LTCG|Win32.ActiveCfg = Release_LTCG|Win32 - {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_LTCG|Win32.Build.0 = Release_LTCG|Win32 + {C59E5129-B453-49B7-A52B-1E104715F76E}.Production|Win32.ActiveCfg = Production|Win32 + {C59E5129-B453-49B7-A52B-1E104715F76E}.Production|Win32.Build.0 = Production|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_PGO_Optimize|Win32.ActiveCfg = Release_PGO|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_PGO_Optimize|Win32.Build.0 = Release_PGO|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_PGO|Win32.ActiveCfg = Release_PGO|Win32 @@ -56,8 +56,8 @@ Global {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug_All|Win32.Build.0 = Debug_All|Win32 {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug|Win32.ActiveCfg = Debug|Win32 {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug|Win32.Build.0 = Debug|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_LTCG|Win32.ActiveCfg = Release_LTCG|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_LTCG|Win32.Build.0 = Release_LTCG|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Production|Win32.ActiveCfg = Production|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Production|Win32.Build.0 = Production|Win32 {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO_Optimize|Win32.ActiveCfg = Release_PGO|Win32 {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO_Optimize|Win32.Build.0 = Release_PGO|Win32 {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO|Win32.ActiveCfg = Release_PGO|Win32 @@ -68,8 +68,8 @@ Global {DA31DA52-6675-48D4-89E0-333A7144397C}.Debug_All|Win32.Build.0 = Debug_All|Win32 {DA31DA52-6675-48D4-89E0-333A7144397C}.Debug|Win32.ActiveCfg = Debug|Win32 {DA31DA52-6675-48D4-89E0-333A7144397C}.Debug|Win32.Build.0 = Debug|Win32 - {DA31DA52-6675-48D4-89E0-333A7144397C}.Release_LTCG|Win32.ActiveCfg = Release_LTCG|Win32 - {DA31DA52-6675-48D4-89E0-333A7144397C}.Release_LTCG|Win32.Build.0 = Release_LTCG|Win32 + {DA31DA52-6675-48D4-89E0-333A7144397C}.Production|Win32.ActiveCfg = Production|Win32 + {DA31DA52-6675-48D4-89E0-333A7144397C}.Production|Win32.Build.0 = Production|Win32 {DA31DA52-6675-48D4-89E0-333A7144397C}.Release_PGO_Optimize|Win32.ActiveCfg = Release_PGO|Win32 {DA31DA52-6675-48D4-89E0-333A7144397C}.Release_PGO_Optimize|Win32.Build.0 = Release_PGO|Win32 {DA31DA52-6675-48D4-89E0-333A7144397C}.Release_PGO|Win32.ActiveCfg = Release_PGO|Win32 @@ -80,8 +80,8 @@ Global {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Debug_All|Win32.Build.0 = Debug_All|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Debug|Win32.ActiveCfg = Debug|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Debug|Win32.Build.0 = Debug|Win32 - {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_LTCG|Win32.ActiveCfg = Release_LTCG|Win32 - {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_LTCG|Win32.Build.0 = Release_LTCG|Win32 + {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Production|Win32.ActiveCfg = Production|Win32 + {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Production|Win32.Build.0 = Production|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_PGO_Optimize|Win32.ActiveCfg = Release_PGO|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_PGO_Optimize|Win32.Build.0 = Release_PGO|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_PGO|Win32.ActiveCfg = Release_PGO|Win32 diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def index 7a8be2a..d7cddf4 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def @@ -3,11 +3,10 @@ EXPORTS ??0CString@WTF@@QAE@PBD@Z ??0CString@WTF@@QAE@PBDI@Z ??0Collator@WTF@@QAE@PBD@Z - ??0DateInstance@JSC@@QAE@PAVExecState@1@N@Z ??0DateInstance@JSC@@QAE@PAVExecState@1@V?$NonNullPassRefPtr@VStructure@JSC@@@WTF@@N@Z ??0DefaultGCActivityCallback@JSC@@QAE@PAVHeap@1@@Z ??0DropAllLocks@JSLock@JSC@@QAE@W4JSLockBehavior@2@@Z - ??0DynamicGlobalObjectScope@JSC@@QAE@PAVExecState@1@PAVJSGlobalObject@1@@Z + ??0DynamicGlobalObjectScope@JSC@@QAE@AAVJSGlobalData@1@PAVJSGlobalObject@1@@Z ??0InternalFunction@JSC@@IAE@PAVJSGlobalData@1@PAVJSGlobalObject@1@V?$NonNullPassRefPtr@VStructure@JSC@@@WTF@@ABVIdentifier@1@@Z ??0JSArray@JSC@@QAE@AAVJSGlobalData@1@V?$NonNullPassRefPtr@VStructure@JSC@@@WTF@@ABVArgList@1@@Z ??0JSArray@JSC@@QAE@V?$NonNullPassRefPtr@VStructure@JSC@@@WTF@@@Z @@ -51,6 +50,7 @@ EXPORTS ?add@PropertyNameArray@JSC@@QAEXPAVStringImpl@WTF@@@Z ?addBytes@MD5@WTF@@QAEXPBEI@Z ?addBytes@SHA1@WTF@@QAEXPBEI@Z + ?addCurrentThread@MachineThreads@JSC@@QAEXXZ ?addPropertyTransition@Structure@JSC@@SA?AV?$PassRefPtr@VStructure@JSC@@@WTF@@PAV12@ABVIdentifier@2@IPAVJSCell@2@AAI@Z ?addPropertyTransitionToExistingStructure@Structure@JSC@@SA?AV?$PassRefPtr@VStructure@JSC@@@WTF@@PAV12@ABVIdentifier@2@IPAVJSCell@2@AAI@Z ?addPropertyWithoutTransition@Structure@JSC@@QAEIABVIdentifier@2@IPAVJSCell@2@@Z @@ -93,23 +93,22 @@ EXPORTS ?constructArray@JSC@@YAPAVJSArray@1@PAVExecState@1@ABVArgList@1@@Z ?constructEmptyArray@JSC@@YAPAVJSArray@1@PAVExecState@1@@Z ?constructEmptyObject@JSC@@YAPAVJSObject@1@PAVExecState@1@@Z - ?constructFunction@JSC@@YAPAVJSObject@1@PAVExecState@1@ABVArgList@1@ABVIdentifier@1@ABVUString@1@H@Z + ?constructFunction@JSC@@YAPAVJSObject@1@PAVExecState@1@PAVJSGlobalObject@1@ABVArgList@1@ABVIdentifier@1@ABVUString@1@H@Z ?convertUTF16ToUTF8@Unicode@WTF@@YA?AW4ConversionResult@12@PAPB_WPB_WPAPADPAD_N@Z ?convertUTF8ToUTF16@Unicode@WTF@@YA?AW4ConversionResult@12@PAPBDPBDPAPA_WPA_W_N@Z ?create@ByteArray@WTF@@SA?AV?$PassRefPtr@VByteArray@WTF@@@2@I@Z ?create@JSGlobalData@JSC@@SA?AV?$PassRefPtr@VJSGlobalData@JSC@@@WTF@@W4ThreadStackType@2@@Z ?create@OpaqueJSString@@SA?AV?$PassRefPtr@UOpaqueJSString@@@WTF@@ABVUString@JSC@@@Z - ?create@RegExp@JSC@@SA?AV?$PassRefPtr@VRegExp@JSC@@@WTF@@PAVJSGlobalData@2@ABVUString@2@1@Z + ?create@RegExp@JSC@@SA?AV?$PassRefPtr@VRegExp@JSC@@@WTF@@PAVJSGlobalData@2@ABVUString@2@W4RegExpFlags@2@@Z ?createEmptyString@SmallStrings@JSC@@AAEXPAVJSGlobalData@2@@Z ?createError@JSC@@YAPAVJSObject@1@PAVExecState@1@ABVUString@1@@Z - ?createInheritorID@JSObject@JSC@@AAEPAVStructure@2@XZ ?createInterruptedExecutionException@JSC@@YAPAVJSObject@1@PAVJSGlobalData@1@@Z ?createLeaked@JSGlobalData@JSC@@SA?AV?$PassRefPtr@VJSGlobalData@JSC@@@WTF@@W4ThreadStackType@2@@Z ?createRangeError@JSC@@YAPAVJSObject@1@PAVExecState@1@ABVUString@1@@Z ?createReferenceError@JSC@@YAPAVJSObject@1@PAVExecState@1@ABVUString@1@@Z ?createSingleCharacterString@SmallStrings@JSC@@AAEXPAVJSGlobalData@2@E@Z ?createStackOverflowError@JSC@@YAPAVJSObject@1@PAVExecState@1@@Z - ?createStructure@JSByteArray@JSC@@SA?AV?$PassRefPtr@VStructure@JSC@@@WTF@@VJSValue@2@PBUClassInfo@2@@Z + ?createStructure@JSByteArray@JSC@@SA?AV?$PassRefPtr@VStructure@JSC@@@WTF@@AAVJSGlobalData@2@VJSValue@2@PBUClassInfo@2@@Z ?createSyntaxError@JSC@@YAPAVJSObject@1@PAVExecState@1@ABVUString@1@@Z ?createTable@HashTable@JSC@@ABEXPAVJSGlobalData@2@@Z ?createThread@WTF@@YAIP6APAXPAX@Z0@Z @@ -147,7 +146,6 @@ EXPORTS ?despecifyDictionaryFunction@Structure@JSC@@QAEXABVIdentifier@2@@Z ?despecifyFunctionTransition@Structure@JSC@@SA?AV?$PassRefPtr@VStructure@JSC@@@WTF@@PAV12@ABVIdentifier@2@@Z ?destroy@Heap@JSC@@QAEXXZ - ?destroyJSGlobalObjectData@JSGlobalObject@JSC@@CAXPAX@Z ?detach@Debugger@JSC@@UAEXPAVJSGlobalObject@2@@Z ?detachThread@WTF@@YAXI@Z ?didTimeOut@TimeoutChecker@JSC@@QAE_NPAVExecState@2@@Z @@ -277,8 +275,9 @@ EXPORTS ?putWithAttributes@JSObject@JSC@@UAEXPAVJSGlobalData@2@IVJSValue@2@I@Z ?randomNumber@WTF@@YANXZ ?recompileAllJSFunctions@Debugger@JSC@@QAEXPAVJSGlobalData@2@@Z - ?registerThread@MachineStackMarker@JSC@@QAEXXZ + ?regExpFlags@JSC@@YA?AW4RegExpFlags@1@ABVUString@1@@Z ?reifyString@StringBuilder@WTF@@AAEXXZ + ?reserveCapacity@StringBuilder@WTF@@QAEXI@Z ?releaseDecommitted@OSAllocator@WTF@@SAXPAXI@Z ?releaseStack@MarkStack@JSC@@CAXPAXI@Z ?reportExtraMemoryCostSlowCase@Heap@JSC@@AAEXI@Z @@ -336,10 +335,9 @@ EXPORTS ?toNumber@JSCell@JSC@@UBENPAVExecState@2@@Z ?toNumber@JSObject@JSC@@UBENPAVExecState@2@@Z ?toNumber@JSString@JSC@@EBENPAVExecState@2@@Z - ?toObject@JSCell@JSC@@UBEPAVJSObject@2@PAVExecState@2@@Z - ?toObject@JSObject@JSC@@UBEPAV12@PAVExecState@2@@Z - ?toObject@JSString@JSC@@EBEPAVJSObject@2@PAVExecState@2@@Z - ?toObjectSlowCase@JSValue@JSC@@ABEPAVJSObject@2@PAVExecState@2@@Z + ?toObject@JSCell@JSC@@UBEPAVJSObject@2@PAVExecState@2@PAVJSGlobalObject@2@@Z + ?toObject@JSObject@JSC@@UBEPAV12@PAVExecState@2@PAVJSGlobalObject@2@@Z + ?toObjectSlowCase@JSValue@JSC@@ABEPAVJSObject@2@PAVExecState@2@PAVJSGlobalObject@2@@Z ?toPrimitive@JSCell@JSC@@UBE?AVJSValue@2@PAVExecState@2@W4PreferredPrimitiveType@2@@Z ?toPrimitive@JSString@JSC@@EBE?AVJSValue@2@PAVExecState@2@W4PreferredPrimitiveType@2@@Z ?toStrictThisObject@JSObject@JSC@@UBE?AVJSValue@2@PAVExecState@2@@Z diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj index 34a9902..30b014a 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj @@ -18,7 +18,7 @@ <Configuration Name="Debug|Win32" ConfigurationType="2" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\JavaScriptCoreCommon.vsprops;.\JavaScriptCoreCF.vsprops" + InheritedPropertySheets=".\JavaScriptCoreDebug.vsprops" CharacterSet="1" > <Tool @@ -79,7 +79,7 @@ <Configuration Name="Release|Win32" ConfigurationType="2" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\JavaScriptCoreCommon.vsprops;.\JavaScriptCoreCF.vsprops" + InheritedPropertySheets=".\JavaScriptCoreRelease.vsprops" CharacterSet="1" > <Tool @@ -140,7 +140,7 @@ <Configuration Name="Release_PGO|Win32" ConfigurationType="2" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\JavaScriptCoreCommon.vsprops;.\JavaScriptCoreCF.vsprops" + InheritedPropertySheets=".\JavaScriptCoreReleasePGO.vsprops" CharacterSet="1" WholeProgramOptimization="2" > @@ -202,7 +202,7 @@ <Configuration Name="Debug_Cairo_CFLite|Win32" ConfigurationType="2" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefinesCairo.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops;.\JavaScriptCoreCommon.vsprops;.\JavaScriptCoreCFLite.vsprops" + InheritedPropertySheets=".\JavaScriptCoreDebugCairoCFLite.vsprops" CharacterSet="1" > <Tool @@ -263,7 +263,7 @@ <Configuration Name="Release_Cairo_CFLite|Win32" ConfigurationType="2" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefinesCairo.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops;.\JavaScriptCoreCommon.vsprops;.\JavaScriptCoreCFLite.vsprops" + InheritedPropertySheets=".\JavaScriptCoreReleaseCairoCFLite.vsprops" CharacterSet="1" > <Tool @@ -324,7 +324,7 @@ <Configuration Name="Debug_All|Win32" ConfigurationType="2" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\JavaScriptCoreCommon.vsprops;.\JavaScriptCoreCF.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops" + InheritedPropertySheets=".\JavaScriptCoreDebugAll.vsprops" CharacterSet="1" > <Tool @@ -383,9 +383,9 @@ /> </Configuration> <Configuration - Name="Release_LTCG|Win32" + Name="Production|Win32" ConfigurationType="2" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\JavaScriptCoreCommon.vsprops;.\JavaScriptCoreCF.vsprops" + InheritedPropertySheets=".\JavaScriptCoreProduction.vsprops" CharacterSet="1" WholeProgramOptimization="1" > @@ -447,7 +447,7 @@ <Configuration Name="Release_PGO_Optimize|Win32" ConfigurationType="2" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\JavaScriptCoreCommon.vsprops;.\JavaScriptCoreCF.vsprops;.\JavaScriptCorePGOOptimize.vsprops" + InheritedPropertySheets=".\JavaScriptCoreReleasePGOOptimize.vsprops" CharacterSet="1" WholeProgramOptimization="4" > @@ -1960,6 +1960,22 @@ RelativePath="..\..\collector\handles\HandleHeap.h" > </File> + <File + RelativePath="..\..\collector\handles\HandleStack.cpp" + > + </File> + <File + RelativePath="..\..\collector\handles\HandleStack.h" + > + </File> + <File + RelativePath="..\..\collector\handles\Local.h" + > + </File> + <File + RelativePath="..\..\collector\handles\LocalScope.h" + > + </File> </Filter> </Filter> <File diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreDebug.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreDebug.vsprops new file mode 100644 index 0000000..0afe222 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreDebug.vsprops @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="JavaScriptCoreDebug" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops; + .\JavaScriptCoreCommon.vsprops; + .\JavaScriptCoreCF.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreDebugAll.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreDebugAll.vsprops new file mode 100644 index 0000000..8cd1130 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreDebugAll.vsprops @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="JavaScriptCoreDebugAll" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops; + .\JavaScriptCoreCommon.vsprops; + .\JavaScriptCoreCF.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreDebugCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreDebugCairoCFLite.vsprops new file mode 100644 index 0000000..ea0806d --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreDebugCairoCFLite.vsprops @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="JavaScriptCoreDebugCairoCFLite" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefinesCairo.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops; + .\JavaScriptCoreCommon.vsprops; + .\JavaScriptCoreCFLite.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj index 2437071..ebff713 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj @@ -43,7 +43,7 @@ /> </Configuration> <Configuration - Name="Release_LTCG|Win32" + Name="Production|Win32" ConfigurationType="0" InheritedPropertySheets=".\JavaScriptCoreGeneratedCommon.vsprops" > diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreProduction.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreProduction.vsprops new file mode 100644 index 0000000..1d8e82d --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreProduction.vsprops @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="JavaScriptCoreProduction" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops; + .\JavaScriptCoreCommon.vsprops; + .\JavaScriptCoreCF.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreRelease.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreRelease.vsprops new file mode 100644 index 0000000..e4612c3 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreRelease.vsprops @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="JavaScriptCoreRelease" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + .\JavaScriptCoreCommon.vsprops; + .\JavaScriptCoreCF.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleaseCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleaseCairoCFLite.vsprops new file mode 100644 index 0000000..64699b5 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleaseCairoCFLite.vsprops @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="JavaScriptCoreReleaseCairoCFLite" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefinesCairo.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops; + .\JavaScriptCoreCommon.vsprops; + .\JavaScriptCoreCFLite.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGO.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGO.vsprops new file mode 100644 index 0000000..ada0b8e --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGO.vsprops @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="JavaScriptCoreReleasePGO" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops; + .\JavaScriptCoreCommon.vsprops; + .\JavaScriptCoreCF.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGOOptimize.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGOOptimize.vsprops new file mode 100644 index 0000000..3e207e7 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGOOptimize.vsprops @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="JavaScriptCoreReleasePGOOptimize" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops; + .\JavaScriptCoreCommon.vsprops; + .\JavaScriptCoreCF.vsprops; + .\JavaScriptCorePGOOptimize.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln index 1109c33..1e24f28 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln @@ -22,7 +22,7 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_All|Win32 = Debug_All|Win32 Debug|Win32 = Debug|Win32 - Release_LTCG|Win32 = Release_LTCG|Win32 + Production|Win32 = Production|Win32 Release_PGO_Optimize|Win32 = Release_PGO_Optimize|Win32 Release_PGO|Win32 = Release_PGO|Win32 Release|Win32 = Release|Win32 @@ -32,8 +32,8 @@ Global {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Debug_All|Win32.Build.0 = Debug_All|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Debug|Win32.ActiveCfg = Debug|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Debug|Win32.Build.0 = Debug|Win32 - {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_LTCG|Win32.ActiveCfg = Release_LTCG|Win32 - {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_LTCG|Win32.Build.0 = Release_LTCG|Win32 + {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Production|Win32.ActiveCfg = Production|Win32 + {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Production|Win32.Build.0 = Production|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_PGO_Optimize|Win32.ActiveCfg = Release_PGO_Optimize|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_PGO_Optimize|Win32.Build.0 = Release_PGO_Optimize|Win32 {011D10F1-B656-4A1B-A0C3-3842F02122C5}.Release_PGO|Win32.ActiveCfg = Release_PGO|Win32 @@ -44,8 +44,8 @@ Global {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug_All|Win32.Build.0 = Debug_All|Win32 {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug|Win32.ActiveCfg = Debug|Win32 {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug|Win32.Build.0 = Debug|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_LTCG|Win32.ActiveCfg = Release_LTCG|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_LTCG|Win32.Build.0 = Release_LTCG|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Production|Win32.ActiveCfg = Production|Win32 + {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Production|Win32.Build.0 = Production|Win32 {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO_Optimize|Win32.ActiveCfg = Release_PGO|Win32 {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO_Optimize|Win32.Build.0 = Release_PGO|Win32 {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO|Win32.ActiveCfg = Release_PGO|Win32 @@ -56,8 +56,8 @@ Global {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Debug_All|Win32.Build.0 = Debug_All|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Debug|Win32.ActiveCfg = Debug|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Debug|Win32.Build.0 = Debug|Win32 - {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_LTCG|Win32.ActiveCfg = Release_LTCG|Win32 - {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_LTCG|Win32.Build.0 = Release_LTCG|Win32 + {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Production|Win32.ActiveCfg = Production|Win32 + {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Production|Win32.Build.0 = Production|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_PGO_Optimize|Win32.ActiveCfg = Release_PGO|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_PGO_Optimize|Win32.Build.0 = Release_PGO|Win32 {4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}.Release_PGO|Win32.ActiveCfg = Release_PGO|Win32 @@ -68,8 +68,8 @@ Global {C59E5129-B453-49B7-A52B-1E104715F76E}.Debug_All|Win32.Build.0 = Debug_All|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Debug|Win32.ActiveCfg = Debug|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Debug|Win32.Build.0 = Debug|Win32 - {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_LTCG|Win32.ActiveCfg = Release_LTCG|Win32 - {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_LTCG|Win32.Build.0 = Release_LTCG|Win32 + {C59E5129-B453-49B7-A52B-1E104715F76E}.Production|Win32.ActiveCfg = Production|Win32 + {C59E5129-B453-49B7-A52B-1E104715F76E}.Production|Win32.Build.0 = Production|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_PGO_Optimize|Win32.ActiveCfg = Release_PGO|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_PGO_Optimize|Win32.Build.0 = Release_PGO|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_PGO|Win32.ActiveCfg = Release_PGO|Win32 diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj index 8f0cfcb..aa337b3 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj @@ -18,7 +18,7 @@ <Configuration Name="Debug|Win32" ConfigurationType="4" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\WTFCommon.vsprops" + InheritedPropertySheets=".\WTFDebug.vsprops" CharacterSet="1" > <Tool @@ -70,7 +70,7 @@ <Configuration Name="Release|Win32" ConfigurationType="4" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\WTFCommon.vsprops" + InheritedPropertySheets=".\WTFRelease.vsprops" CharacterSet="1" > <Tool @@ -122,7 +122,7 @@ <Configuration Name="Debug_All|Win32" ConfigurationType="4" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\WTFCommon.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops" + InheritedPropertySheets=".\WTFDebugAll.vsprops" CharacterSet="1" > <Tool @@ -172,9 +172,9 @@ /> </Configuration> <Configuration - Name="Release_LTCG|Win32" + Name="Production|Win32" ConfigurationType="4" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\WTFCommon.vsprops" + InheritedPropertySheets=".\WTFProduction.vsprops" CharacterSet="1" WholeProgramOptimization="1" > @@ -227,7 +227,7 @@ <Configuration Name="Release_Cairo_CFLite|Win32" ConfigurationType="4" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefinesCairo.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops;.\WTFCommon.vsprops" + InheritedPropertySheets=".\WTFReleaseCairoCFLite.vsprops" CharacterSet="1" > <Tool @@ -279,7 +279,7 @@ <Configuration Name="Debug_Cairo_CFLite|Win32" ConfigurationType="4" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefinesCairo.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops;.\WTFCommon.vsprops" + InheritedPropertySheets=".\WTFDebugCairoCFLite.vsprops" CharacterSet="1" > <Tool @@ -331,7 +331,7 @@ <Configuration Name="Release_PGO|Win32" ConfigurationType="4" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\WTFCommon.vsprops" + InheritedPropertySheets=".\WTFReleasePGO.vsprops" CharacterSet="1" > <Tool @@ -632,7 +632,7 @@ /> </FileConfiguration> <FileConfiguration - Name="Release_LTCG|Win32" + Name="Production|Win32" > <Tool Name="VCCLCompilerTool" @@ -705,6 +705,10 @@ > </File> <File + RelativePath="..\..\wtf\HexNumber.h" + > + </File> + <File RelativePath="..\..\wtf\ListHashSet.h" > </File> @@ -965,7 +969,7 @@ > </File> <File - RelativePath="..\..\wtf\ThreadSafeShared.h" + RelativePath="..\..\wtf\ThreadSafeRefCounted.h" > </File> <File diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebug.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebug.vsprops new file mode 100644 index 0000000..132b5c7 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebug.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="WTFDebug" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops; + .\WTFCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebugAll.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebugAll.vsprops new file mode 100644 index 0000000..061f2ed --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebugAll.vsprops @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="WTFDebugAll" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops; + .\WTFCommon.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebugCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebugCairoCFLite.vsprops new file mode 100644 index 0000000..7965652 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebugCairoCFLite.vsprops @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="WTFDebugCairoCFLite" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefinesCairo.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops; + .\WTFCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFProduction.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFProduction.vsprops new file mode 100644 index 0000000..3de342c --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFProduction.vsprops @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="WTFProduction" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops; + .\WTFCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFRelease.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFRelease.vsprops new file mode 100644 index 0000000..3960f98 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFRelease.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="WTFRelease" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + .\WTFCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFReleaseCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFReleaseCairoCFLite.vsprops new file mode 100644 index 0000000..3267d79 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFReleaseCairoCFLite.vsprops @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="WTFReleaseCairoCFLite" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefinesCairo.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops; + .\WTFCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFReleasePGO.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFReleasePGO.vsprops new file mode 100644 index 0000000..ac4f8a5 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFReleasePGO.vsprops @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="WTFReleasePGO" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops; + .\WTFCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj index ebcfd8e..a650cd2 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj @@ -18,7 +18,7 @@ <Configuration Name="Debug|Win32" ConfigurationType="1" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\jscCommon.vsprops" + InheritedPropertySheets=".\jscDebug.vsprops" CharacterSet="1" > <Tool @@ -79,7 +79,7 @@ <Configuration Name="Release|Win32" ConfigurationType="1" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\jscCommon.vsprops" + InheritedPropertySheets=".\jscRelease.vsprops" CharacterSet="1" > <Tool @@ -140,7 +140,7 @@ <Configuration Name="Debug_Cairo_CFLite|Win32" ConfigurationType="1" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops;.\jscCommon.vsprops" + InheritedPropertySheets=".\jscDebugCairoCFLite.vsprops" CharacterSet="1" > <Tool @@ -201,7 +201,7 @@ <Configuration Name="Debug_All|Win32" ConfigurationType="1" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\jscCommon.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops" + InheritedPropertySheets=".\jscDebugAll.vsprops" CharacterSet="1" > <Tool @@ -260,9 +260,9 @@ /> </Configuration> <Configuration - Name="Release_LTCG|Win32" + Name="Production|Win32" ConfigurationType="1" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\jscCommon.vsprops" + InheritedPropertySheets=".\jscProduction.vsprops" CharacterSet="1" WholeProgramOptimization="1" > @@ -324,7 +324,7 @@ <Configuration Name="Release_Cairo_CFLite|Win32" ConfigurationType="1" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops;.\jscCommon.vsprops" + InheritedPropertySheets=".\jscReleaseCairoCFLite.vsprops" CharacterSet="1" > <Tool @@ -385,7 +385,7 @@ <Configuration Name="Release_PGO|Win32" ConfigurationType="1" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\jscCommon.vsprops" + InheritedPropertySheets=".\jscReleasePGO.vsprops" CharacterSet="1" > <Tool diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscDebug.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscDebug.vsprops new file mode 100644 index 0000000..fa6dc68 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscDebug.vsprops @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="jscDebug" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops; + .\jscCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscDebugAll.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscDebugAll.vsprops new file mode 100644 index 0000000..6090c60 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscDebugAll.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="jscDebugAll" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops; + .\jscCommon.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscDebugCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscDebugCairoCFLite.vsprops new file mode 100644 index 0000000..c1868a8 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscDebugCairoCFLite.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="jscDebugCairoCFLite" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops; + .\jscCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscProduction.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscProduction.vsprops new file mode 100644 index 0000000..408871b --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscProduction.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="jscProduction" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops; + .\jscCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscRelease.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscRelease.vsprops new file mode 100644 index 0000000..ba9b288 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscRelease.vsprops @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="jscRelease" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + .\jscCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscReleaseCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscReleaseCairoCFLite.vsprops new file mode 100644 index 0000000..2104fe4 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscReleaseCairoCFLite.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="jscReleaseCairoCFLite" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops; + .\jscCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscReleasePGO.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscReleasePGO.vsprops new file mode 100644 index 0000000..78f3672 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscReleasePGO.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="jscReleasePGO" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops; + .\jscCommon.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapi.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapi.vcproj index 5b18032..1dfdd1e 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapi.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapi.vcproj @@ -18,7 +18,7 @@ <Configuration Name="Debug|Win32" ConfigurationType="1" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\testapiCommon.vsprops;..\JavaScriptCore\JavaScriptCoreCF.vsprops" + InheritedPropertySheets=".\testapiDebug.vsprops" CharacterSet="1" > <Tool @@ -79,7 +79,7 @@ <Configuration Name="Release|Win32" ConfigurationType="1" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\testapiCommon.vsprops;..\JavaScriptCore\JavaScriptCoreCF.vsprops" + InheritedPropertySheets=".\testapiRelease.vsprops" CharacterSet="1" > <Tool @@ -140,7 +140,7 @@ <Configuration Name="Debug_Cairo_CFLite|Win32" ConfigurationType="1" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops;.\testapiCommon.vsprops;..\JavaScriptCore\JavaScriptCoreCFLite.vsprops" + InheritedPropertySheets=".\testapiDebugCairoCFLite.vsprops" CharacterSet="1" > <Tool @@ -201,7 +201,7 @@ <Configuration Name="Release_Cairo_CFLite|Win32" ConfigurationType="1" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops;.\testapiCommon.vsprops;..\JavaScriptCore\JavaScriptCoreCFLite.vsprops" + InheritedPropertySheets=".\testapiReleaseCairoCFLite.vsprops" CharacterSet="1" > <Tool @@ -262,7 +262,7 @@ <Configuration Name="Debug_All|Win32" ConfigurationType="1" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\testapiCommon.vsprops;..\JavaScriptCore\JavaScriptCoreCF.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops" + InheritedPropertySheets=".\testapiDebugAll.vsprops" CharacterSet="1" > <Tool @@ -321,9 +321,9 @@ /> </Configuration> <Configuration - Name="Release_LTCG|Win32" + Name="Production|Win32" ConfigurationType="1" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\testapiCommon.vsprops;..\JavaScriptCore\JavaScriptCoreCF.vsprops" + InheritedPropertySheets=".\testapiProduction.vsprops" CharacterSet="1" WholeProgramOptimization="1" > @@ -430,7 +430,7 @@ /> </FileConfiguration> <FileConfiguration - Name="Release_LTCG|Win32" + Name="Production|Win32" > <Tool Name="VCCLCompilerTool" diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiDebug.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiDebug.vsprops new file mode 100644 index 0000000..ba5e31d --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiDebug.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="testapiDebug" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops; + .\testapiCommon.vsprops; + ..\JavaScriptCore\JavaScriptCoreCF.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiDebugAll.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiDebugAll.vsprops new file mode 100644 index 0000000..cc139f8 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiDebugAll.vsprops @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="testapiDebugAll" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops; + .\testapiCommon.vsprops; + ..\JavaScriptCore\JavaScriptCoreCF.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiDebugCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiDebugCairoCFLite.vsprops new file mode 100644 index 0000000..4e1e11f --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiDebugCairoCFLite.vsprops @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="testapiDebugCairoCFLite" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops; + .\testapiCommon.vsprops; + ..\JavaScriptCore\JavaScriptCoreCFLite.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiProduction.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiProduction.vsprops new file mode 100644 index 0000000..03fceab --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiProduction.vsprops @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="testapiProduction" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops; + .\testapiCommon.vsprops; + ..\JavaScriptCore\JavaScriptCoreCF.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiRelease.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiRelease.vsprops new file mode 100644 index 0000000..1c041ff --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiRelease.vsprops @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="testapiRelease" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + .\testapiCommon.vsprops; + ..\JavaScriptCore\JavaScriptCoreCF.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiReleaseCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiReleaseCairoCFLite.vsprops new file mode 100644 index 0000000..c025283 --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/testapi/testapiReleaseCairoCFLite.vsprops @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="testapiReleaseCairoCFLite" + InheritedPropertySheets=" + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops; + $(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops; + .\testapiCommon.vsprops; + ..\JavaScriptCore\JavaScriptCoreCFLite.vsprops" + > +</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index 9f8d49a..44e108c 100644 --- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -121,6 +121,7 @@ 14469DEC107EC7E700650446 /* StringObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC18C3C20E16EE3300B34460 /* StringObject.cpp */; }; 14469DED107EC7E700650446 /* StringPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC18C3C50E16EE3300B34460 /* StringPrototype.cpp */; }; 14469DEE107EC7E700650446 /* UString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A8850255597D01FF60F7 /* UString.cpp */; }; + 144836E7132DA7BE005BE785 /* ConservativeSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 149DAAF212EB559D0083B12B /* ConservativeSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; 146AAB380B66A94400E55F16 /* JSStringRefCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 146AAB370B66A94400E55F16 /* JSStringRefCF.cpp */; }; 146B16D812EB5B59001BEC1B /* ConservativeSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 146B14DB12EB5B12001BEC1B /* ConservativeSet.cpp */; }; 146FE51211A710430087AE66 /* JITCall32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 146FE51111A710430087AE66 /* JITCall32_64.cpp */; }; @@ -209,7 +210,8 @@ 655EB29B10CE2581001A990E /* NodesCodegen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 655EB29A10CE2581001A990E /* NodesCodegen.cpp */; }; 65DFC93308EA173A00F7300B /* HashTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65DFC92D08EA173A00F7300B /* HashTable.cpp */; }; 65E1A3DF122B894500B26097 /* NonCopyingSort.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E1A2F4122B880D00B26097 /* NonCopyingSort.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 65FDE49C0BDD1D4A00E80111 /* Assertions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65E217B808E7EECC0023E5F6 /* Assertions.cpp */; settings = {COMPILER_FLAGS = "-Wno-missing-format-attribute"; }; }; + 65FDE49C0BDD1D4A00E80111 /* Assertions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65E217B808E7EECC0023E5F6 /* Assertions.cpp */; }; + 7186A6EC13100BA5004479E1 /* HexNumber.h in Headers */ = {isa = PBXBuildFile; fileRef = 7186A6E813100B57004479E1 /* HexNumber.h */; settings = {ATTRIBUTES = (Private, ); }; }; 76FB9F0F12E851860051A2EB /* SHA1.h in Headers */ = {isa = PBXBuildFile; fileRef = 76FB9F0E12E851860051A2EB /* SHA1.h */; settings = {ATTRIBUTES = (Private, ); }; }; 76FB9F1112E851960051A2EB /* SHA1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76FB9F1012E851960051A2EB /* SHA1.cpp */; }; 7E4EE7090EBB7963005934AA /* StructureChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E4EE7080EBB7963005934AA /* StructureChain.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -280,6 +282,25 @@ 86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */; }; 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E116B00FE75AC800B512BC /* CodeLocation.h */; }; 86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E85538111B9968001AF51E /* JSStringBuilder.h */; }; + 86EC9DC41328DF82002B2AD7 /* DFGByteCodeParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EC9DB41328DF82002B2AD7 /* DFGByteCodeParser.cpp */; }; + 86EC9DC51328DF82002B2AD7 /* DFGByteCodeParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EC9DB51328DF82002B2AD7 /* DFGByteCodeParser.h */; }; + 86EC9DC61328DF82002B2AD7 /* DFGGenerationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EC9DB61328DF82002B2AD7 /* DFGGenerationInfo.h */; }; + 86EC9DC71328DF82002B2AD7 /* DFGGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EC9DB71328DF82002B2AD7 /* DFGGraph.cpp */; }; + 86EC9DC81328DF82002B2AD7 /* DFGGraph.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EC9DB81328DF82002B2AD7 /* DFGGraph.h */; }; + 86EC9DC91328DF82002B2AD7 /* DFGJITCodeGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EC9DB91328DF82002B2AD7 /* DFGJITCodeGenerator.cpp */; }; + 86EC9DCA1328DF82002B2AD7 /* DFGJITCodeGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EC9DBA1328DF82002B2AD7 /* DFGJITCodeGenerator.h */; }; + 86EC9DCB1328DF82002B2AD7 /* DFGJITCompiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EC9DBB1328DF82002B2AD7 /* DFGJITCompiler.cpp */; }; + 86EC9DCC1328DF82002B2AD7 /* DFGJITCompiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EC9DBC1328DF82002B2AD7 /* DFGJITCompiler.h */; }; + 86EC9DCD1328DF82002B2AD7 /* DFGNonSpeculativeJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EC9DBD1328DF82002B2AD7 /* DFGNonSpeculativeJIT.cpp */; }; + 86EC9DCE1328DF82002B2AD7 /* DFGNonSpeculativeJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EC9DBE1328DF82002B2AD7 /* DFGNonSpeculativeJIT.h */; }; + 86EC9DCF1328DF82002B2AD7 /* DFGOperations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EC9DBF1328DF82002B2AD7 /* DFGOperations.cpp */; }; + 86EC9DD01328DF82002B2AD7 /* DFGOperations.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EC9DC01328DF82002B2AD7 /* DFGOperations.h */; }; + 86EC9DD11328DF82002B2AD7 /* DFGRegisterBank.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EC9DC11328DF82002B2AD7 /* DFGRegisterBank.h */; }; + 86EC9DD21328DF82002B2AD7 /* DFGSpeculativeJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EC9DC21328DF82002B2AD7 /* DFGSpeculativeJIT.cpp */; }; + 86EC9DD31328DF82002B2AD7 /* DFGSpeculativeJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = 86EC9DC31328DF82002B2AD7 /* DFGSpeculativeJIT.h */; }; + 86ECA3EA132DEF1C002B2AD7 /* DFGNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ECA3E9132DEF1C002B2AD7 /* DFGNode.h */; }; + 86ECA3FA132DF25A002B2AD7 /* DFGScoreBoard.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ECA3F9132DF25A002B2AD7 /* DFGScoreBoard.h */; }; + 86ECA4F1132EAA6D002B2AD7 /* DFGAliasTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ECA4F0132EAA6D002B2AD7 /* DFGAliasTracker.h */; }; 86F38859121130CA007A7CE3 /* AtomicStringHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F38858121130CA007A7CE3 /* AtomicStringHash.h */; settings = {ATTRIBUTES = (Private, ); }; }; 90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */; }; 90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 90213E3C123A40C200D422F3 /* MemoryStatistics.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -355,6 +376,10 @@ A74DE1D0120B875600D40D5B /* ARMv7Assembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A74DE1CB120B86D600D40D5B /* ARMv7Assembler.cpp */; }; A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */; }; A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A76BE39F132EEA7C008F7F0B /* HandleStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A76BE1B7132DAC68008F7F0B /* HandleStack.cpp */; }; + A76BE3A0132EEA7C008F7F0B /* HandleStack.h in Headers */ = {isa = PBXBuildFile; fileRef = A76BE1B8132DAC68008F7F0B /* HandleStack.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A76BE3A1132EEA7C008F7F0B /* Local.h in Headers */ = {isa = PBXBuildFile; fileRef = A76BE1B5132DABF5008F7F0B /* Local.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A76BE3A2132EEA7C008F7F0B /* LocalScope.h in Headers */ = {isa = PBXBuildFile; fileRef = A76BE1B6132DAC24008F7F0B /* LocalScope.h */; settings = {ATTRIBUTES = (Private, ); }; }; A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = A76C51741182748D00715B05 /* JSInterfaceJIT.h */; }; A7795590101A74D500114E55 /* MarkStack.h in Headers */ = {isa = PBXBuildFile; fileRef = A779558F101A74D500114E55 /* MarkStack.h */; settings = {ATTRIBUTES = (Private, ); }; }; A783A0D111A36DCA00563D20 /* JSObjectWithGlobalObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A783A0D011A36DCA00563D20 /* JSObjectWithGlobalObject.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -531,7 +556,7 @@ BC3135650F302FA3003DFD3A /* DebuggerActivation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC3135630F302FA3003DFD3A /* DebuggerActivation.cpp */; }; BC5F7BBE11823B590052C02C /* Atomics.h in Headers */ = {isa = PBXBuildFile; fileRef = BC5F7BBB11823B590052C02C /* Atomics.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC5F7BBF11823B590052C02C /* ThreadingPrimitives.h in Headers */ = {isa = PBXBuildFile; fileRef = BC5F7BBC11823B590052C02C /* ThreadingPrimitives.h */; settings = {ATTRIBUTES = (Private, ); }; }; - BC5F7BC011823B590052C02C /* ThreadSafeShared.h in Headers */ = {isa = PBXBuildFile; fileRef = BC5F7BBD11823B590052C02C /* ThreadSafeShared.h */; settings = {ATTRIBUTES = (Private, ); }; }; + BC5F7BC011823B590052C02C /* ThreadSafeRefCounted.h in Headers */ = {isa = PBXBuildFile; fileRef = BC5F7BBD11823B590052C02C /* ThreadSafeRefCounted.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; BC756FC90E2031B200DE7D12 /* JSGlobalObjectFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */; }; BC7F8FB90E19D1C3008632C0 /* JSNumberCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7F8FB80E19D1C3008632C0 /* JSNumberCell.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -850,6 +875,7 @@ 65EA73620BAE35D1001BB560 /* CommonIdentifiers.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CommonIdentifiers.cpp; sourceTree = "<group>"; }; 65EA73630BAE35D1001BB560 /* CommonIdentifiers.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CommonIdentifiers.h; sourceTree = "<group>"; }; 704FD35305697E6D003DBED9 /* BooleanObject.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = BooleanObject.h; sourceTree = "<group>"; tabWidth = 8; }; + 7186A6E813100B57004479E1 /* HexNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HexNumber.h; sourceTree = "<group>"; }; 76FB9F0E12E851860051A2EB /* SHA1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHA1.h; sourceTree = "<group>"; }; 76FB9F1012E851960051A2EB /* SHA1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SHA1.cpp; sourceTree = "<group>"; }; 7E2C6C980D31C6B6002D44E2 /* ScopeChainMark.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScopeChainMark.h; sourceTree = "<group>"; }; @@ -922,6 +948,25 @@ 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocatorFixedVMPool.cpp; sourceTree = "<group>"; }; 86E116B00FE75AC800B512BC /* CodeLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeLocation.h; sourceTree = "<group>"; }; 86E85538111B9968001AF51E /* JSStringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringBuilder.h; sourceTree = "<group>"; }; + 86EC9DB41328DF82002B2AD7 /* DFGByteCodeParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGByteCodeParser.cpp; path = dfg/DFGByteCodeParser.cpp; sourceTree = "<group>"; }; + 86EC9DB51328DF82002B2AD7 /* DFGByteCodeParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGByteCodeParser.h; path = dfg/DFGByteCodeParser.h; sourceTree = "<group>"; }; + 86EC9DB61328DF82002B2AD7 /* DFGGenerationInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGGenerationInfo.h; path = dfg/DFGGenerationInfo.h; sourceTree = "<group>"; }; + 86EC9DB71328DF82002B2AD7 /* DFGGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGGraph.cpp; path = dfg/DFGGraph.cpp; sourceTree = "<group>"; }; + 86EC9DB81328DF82002B2AD7 /* DFGGraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGGraph.h; path = dfg/DFGGraph.h; sourceTree = "<group>"; }; + 86EC9DB91328DF82002B2AD7 /* DFGJITCodeGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGJITCodeGenerator.cpp; path = dfg/DFGJITCodeGenerator.cpp; sourceTree = "<group>"; }; + 86EC9DBA1328DF82002B2AD7 /* DFGJITCodeGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGJITCodeGenerator.h; path = dfg/DFGJITCodeGenerator.h; sourceTree = "<group>"; }; + 86EC9DBB1328DF82002B2AD7 /* DFGJITCompiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGJITCompiler.cpp; path = dfg/DFGJITCompiler.cpp; sourceTree = "<group>"; }; + 86EC9DBC1328DF82002B2AD7 /* DFGJITCompiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGJITCompiler.h; path = dfg/DFGJITCompiler.h; sourceTree = "<group>"; }; + 86EC9DBD1328DF82002B2AD7 /* DFGNonSpeculativeJIT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNonSpeculativeJIT.cpp; path = dfg/DFGNonSpeculativeJIT.cpp; sourceTree = "<group>"; }; + 86EC9DBE1328DF82002B2AD7 /* DFGNonSpeculativeJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNonSpeculativeJIT.h; path = dfg/DFGNonSpeculativeJIT.h; sourceTree = "<group>"; }; + 86EC9DBF1328DF82002B2AD7 /* DFGOperations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOperations.cpp; path = dfg/DFGOperations.cpp; sourceTree = "<group>"; }; + 86EC9DC01328DF82002B2AD7 /* DFGOperations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOperations.h; path = dfg/DFGOperations.h; sourceTree = "<group>"; }; + 86EC9DC11328DF82002B2AD7 /* DFGRegisterBank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGRegisterBank.h; path = dfg/DFGRegisterBank.h; sourceTree = "<group>"; }; + 86EC9DC21328DF82002B2AD7 /* DFGSpeculativeJIT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGSpeculativeJIT.cpp; path = dfg/DFGSpeculativeJIT.cpp; sourceTree = "<group>"; }; + 86EC9DC31328DF82002B2AD7 /* DFGSpeculativeJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSpeculativeJIT.h; path = dfg/DFGSpeculativeJIT.h; sourceTree = "<group>"; }; + 86ECA3E9132DEF1C002B2AD7 /* DFGNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNode.h; path = dfg/DFGNode.h; sourceTree = "<group>"; }; + 86ECA3F9132DF25A002B2AD7 /* DFGScoreBoard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGScoreBoard.h; path = dfg/DFGScoreBoard.h; sourceTree = "<group>"; }; + 86ECA4F0132EAA6D002B2AD7 /* DFGAliasTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAliasTracker.h; path = dfg/DFGAliasTracker.h; sourceTree = "<group>"; }; 86F38858121130CA007A7CE3 /* AtomicStringHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AtomicStringHash.h; path = text/AtomicStringHash.h; sourceTree = "<group>"; }; 90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryStatistics.cpp; sourceTree = "<group>"; }; 90213E3C123A40C200D422F3 /* MemoryStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryStatistics.h; sourceTree = "<group>"; }; @@ -1030,6 +1075,10 @@ A74B3498102A5F8E0032AB98 /* MarkStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkStack.cpp; sourceTree = "<group>"; }; A74DE1CB120B86D600D40D5B /* ARMv7Assembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMv7Assembler.cpp; sourceTree = "<group>"; }; A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITArithmetic32_64.cpp; sourceTree = "<group>"; }; + A76BE1B5132DABF5008F7F0B /* Local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Local.h; path = collector/handles/Local.h; sourceTree = "<group>"; }; + A76BE1B6132DAC24008F7F0B /* LocalScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LocalScope.h; path = collector/handles/LocalScope.h; sourceTree = "<group>"; }; + A76BE1B7132DAC68008F7F0B /* HandleStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HandleStack.cpp; path = collector/handles/HandleStack.cpp; sourceTree = "<group>"; }; + A76BE1B8132DAC68008F7F0B /* HandleStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HandleStack.h; path = collector/handles/HandleStack.h; sourceTree = "<group>"; }; A76C51741182748D00715B05 /* JSInterfaceJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInterfaceJIT.h; sourceTree = "<group>"; }; A779558F101A74D500114E55 /* MarkStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkStack.h; sourceTree = "<group>"; }; A783A0D011A36DCA00563D20 /* JSObjectWithGlobalObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSObjectWithGlobalObject.h; sourceTree = "<group>"; }; @@ -1125,7 +1174,7 @@ BC337BEA0E1B00CB0076918A /* Error.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Error.cpp; sourceTree = "<group>"; }; BC5F7BBB11823B590052C02C /* Atomics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Atomics.h; sourceTree = "<group>"; }; BC5F7BBC11823B590052C02C /* ThreadingPrimitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadingPrimitives.h; sourceTree = "<group>"; }; - BC5F7BBD11823B590052C02C /* ThreadSafeShared.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadSafeShared.h; sourceTree = "<group>"; }; + BC5F7BBD11823B590052C02C /* ThreadSafeRefCounted.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadSafeRefCounted.h; sourceTree = "<group>"; }; BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClassInfo.h; sourceTree = "<group>"; }; BC756FC60E2031B200DE7D12 /* JSGlobalObjectFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalObjectFunctions.cpp; sourceTree = "<group>"; }; BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObjectFunctions.h; sourceTree = "<group>"; }; @@ -1317,6 +1366,7 @@ 7E39D81D0EC38EFA003AF11A /* bytecompiler */, A7E4FC8312F8E4A300AF4CF4 /* collector */, 1480DB9A0DDC2231003CFDF2 /* debugger */, + 86EC9DB31328DF44002B2AD7 /* dfg */, 1429D77A0ED20D7300B89619 /* interpreter */, 1429D92C0ED22D7000B89619 /* jit */, 7E39D8370EC3A388003AF11A /* parser */, @@ -1567,6 +1617,7 @@ 65DFC92D08EA173A00F7300B /* HashTable.cpp */, 65DFC92E08EA173A00F7300B /* HashTable.h */, 65DFC92F08EA173A00F7300B /* HashTraits.h */, + 7186A6E813100B57004479E1 /* HexNumber.h */, 657EB7450B708F540063461B /* ListHashSet.h */, 148A1626095D16BB00666D0D /* ListRefPtr.h */, E1EE79270D6C964500FEA3BA /* Locker.h */, @@ -1634,7 +1685,7 @@ E1EE79220D6C95CD00FEA3BA /* Threading.h */, BC5F7BBC11823B590052C02C /* ThreadingPrimitives.h */, E1EE793C0D6C9B9200FEA3BA /* ThreadingPthreads.cpp */, - BC5F7BBD11823B590052C02C /* ThreadSafeShared.h */, + BC5F7BBD11823B590052C02C /* ThreadSafeRefCounted.h */, E1B7C8BD0DA3A3360074B0DC /* ThreadSpecific.h */, 0B330C260F38C62300692DE3 /* TypeTraits.cpp */, 0B4D7E620F319AC800AD7E58 /* TypeTraits.h */, @@ -1946,6 +1997,32 @@ name = yarr; sourceTree = "<group>"; }; + 86EC9DB31328DF44002B2AD7 /* dfg */ = { + isa = PBXGroup; + children = ( + 86ECA4F0132EAA6D002B2AD7 /* DFGAliasTracker.h */, + 86EC9DB41328DF82002B2AD7 /* DFGByteCodeParser.cpp */, + 86EC9DB51328DF82002B2AD7 /* DFGByteCodeParser.h */, + 86EC9DB61328DF82002B2AD7 /* DFGGenerationInfo.h */, + 86EC9DB71328DF82002B2AD7 /* DFGGraph.cpp */, + 86EC9DB81328DF82002B2AD7 /* DFGGraph.h */, + 86EC9DB91328DF82002B2AD7 /* DFGJITCodeGenerator.cpp */, + 86EC9DBA1328DF82002B2AD7 /* DFGJITCodeGenerator.h */, + 86EC9DBB1328DF82002B2AD7 /* DFGJITCompiler.cpp */, + 86EC9DBC1328DF82002B2AD7 /* DFGJITCompiler.h */, + 86ECA3E9132DEF1C002B2AD7 /* DFGNode.h */, + 86EC9DBD1328DF82002B2AD7 /* DFGNonSpeculativeJIT.cpp */, + 86EC9DBE1328DF82002B2AD7 /* DFGNonSpeculativeJIT.h */, + 86EC9DBF1328DF82002B2AD7 /* DFGOperations.cpp */, + 86EC9DC01328DF82002B2AD7 /* DFGOperations.h */, + 86EC9DC11328DF82002B2AD7 /* DFGRegisterBank.h */, + 86ECA3F9132DF25A002B2AD7 /* DFGScoreBoard.h */, + 86EC9DC21328DF82002B2AD7 /* DFGSpeculativeJIT.cpp */, + 86EC9DC31328DF82002B2AD7 /* DFGSpeculativeJIT.h */, + ); + name = dfg; + sourceTree = "<group>"; + }; 932FC3C20824BB70005B3C75 /* Resources */ = { isa = PBXGroup; children = ( @@ -2074,6 +2151,10 @@ A7E4FC8812F8E4CA00AF4CF4 /* Handle.h */, A7E4FC8912F8E4CA00AF4CF4 /* HandleHeap.cpp */, A7E4FC8A12F8E4CA00AF4CF4 /* HandleHeap.h */, + A76BE1B7132DAC68008F7F0B /* HandleStack.cpp */, + A76BE1B8132DAC68008F7F0B /* HandleStack.h */, + A76BE1B5132DABF5008F7F0B /* Local.h */, + A76BE1B6132DAC24008F7F0B /* LocalScope.h */, ); name = handles; sourceTree = "<group>"; @@ -2160,6 +2241,7 @@ BC18C3F40E16F5CD00B34460 /* Completion.h in Headers */, FDA15C1E12B0305C003A583A /* Complex.h in Headers */, BC18C3F50E16F5CD00B34460 /* config.h in Headers */, + 144836E7132DA7BE005BE785 /* ConservativeSet.h in Headers */, BC18C3F60E16F5CD00B34460 /* ConstructData.h in Headers */, 0BDFFAE00FC6192900D69EF4 /* CrossThreadRefCounted.h in Headers */, 86565743115BE3DA00291F40 /* CString.h in Headers */, @@ -2205,6 +2287,7 @@ BC18C40D0E16F5CD00B34460 /* HashTable.h in Headers */, BC18C40E0E16F5CD00B34460 /* HashTraits.h in Headers */, 140CDE7112DE97B10013CFC5 /* Heap.h in Headers */, + 7186A6EC13100BA5004479E1 /* HexNumber.h in Headers */, BC18C40F0E16F5CD00B34460 /* Identifier.h in Headers */, BC18C4100E16F5CD00B34460 /* InitializeThreading.h in Headers */, 969A07990ED1D3AE00F1F681 /* Instruction.h in Headers */, @@ -2401,7 +2484,7 @@ 18BAB55410DAE066000D945B /* ThreadIdentifierDataPthreads.h in Headers */, BC18C4700E16F5CD00B34460 /* Threading.h in Headers */, BC5F7BBF11823B590052C02C /* ThreadingPrimitives.h in Headers */, - BC5F7BC011823B590052C02C /* ThreadSafeShared.h in Headers */, + BC5F7BC011823B590052C02C /* ThreadSafeRefCounted.h in Headers */, BC18C4710E16F5CD00B34460 /* ThreadSpecific.h in Headers */, A7386556118697B400540279 /* ThunkGenerators.h in Headers */, 14A42E400F4F60EE00599099 /* TimeoutChecker.h in Headers */, @@ -2449,6 +2532,21 @@ A7C40C0A130B057D00D002A1 /* BlockStack.h in Headers */, A7C40C0B130B057D00D002A1 /* SentinelLinkedList.h in Headers */, A7C40C0C130B057D00D002A1 /* SinglyLinkedList.h in Headers */, + A76BE3A0132EEA7C008F7F0B /* HandleStack.h in Headers */, + A76BE3A1132EEA7C008F7F0B /* Local.h in Headers */, + A76BE3A2132EEA7C008F7F0B /* LocalScope.h in Headers */, + 86EC9DC51328DF82002B2AD7 /* DFGByteCodeParser.h in Headers */, + 86EC9DC61328DF82002B2AD7 /* DFGGenerationInfo.h in Headers */, + 86EC9DC81328DF82002B2AD7 /* DFGGraph.h in Headers */, + 86EC9DCA1328DF82002B2AD7 /* DFGJITCodeGenerator.h in Headers */, + 86EC9DCC1328DF82002B2AD7 /* DFGJITCompiler.h in Headers */, + 86EC9DCE1328DF82002B2AD7 /* DFGNonSpeculativeJIT.h in Headers */, + 86EC9DD01328DF82002B2AD7 /* DFGOperations.h in Headers */, + 86EC9DD11328DF82002B2AD7 /* DFGRegisterBank.h in Headers */, + 86EC9DD31328DF82002B2AD7 /* DFGSpeculativeJIT.h in Headers */, + 86ECA3EA132DEF1C002B2AD7 /* DFGNode.h in Headers */, + 86ECA3FA132DF25A002B2AD7 /* DFGScoreBoard.h in Headers */, + 86ECA4F1132EAA6D002B2AD7 /* DFGAliasTracker.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2888,6 +2986,14 @@ 97941A7E1302A098004A3447 /* CryptographicallyRandomNumber.cpp in Sources */, A7E4FC9112F8E4CA00AF4CF4 /* HandleHeap.cpp in Sources */, A7AC25BD1304D146003396DE /* MarkedBlock.cpp in Sources */, + A76BE39F132EEA7C008F7F0B /* HandleStack.cpp in Sources */, + 86EC9DC41328DF82002B2AD7 /* DFGByteCodeParser.cpp in Sources */, + 86EC9DC71328DF82002B2AD7 /* DFGGraph.cpp in Sources */, + 86EC9DC91328DF82002B2AD7 /* DFGJITCodeGenerator.cpp in Sources */, + 86EC9DCB1328DF82002B2AD7 /* DFGJITCompiler.cpp in Sources */, + 86EC9DCD1328DF82002B2AD7 /* DFGNonSpeculativeJIT.cpp in Sources */, + 86EC9DCF1328DF82002B2AD7 /* DFGOperations.cpp in Sources */, + 86EC9DD21328DF82002B2AD7 /* DFGSpeculativeJIT.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Source/JavaScriptCore/Makefile b/Source/JavaScriptCore/Makefile index b9e2a72..cb4c11a 100644 --- a/Source/JavaScriptCore/Makefile +++ b/Source/JavaScriptCore/Makefile @@ -1,2 +1 @@ -OTHER_OPTIONS = -target All include ../Makefile.shared diff --git a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h index 5ebc572..8e81784 100644 --- a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h +++ b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h @@ -145,21 +145,21 @@ public: // Describes an memory operand given by a pointer. For regular load & store // operations an unwrapped void* will be used, rather than using this. struct AbsoluteAddress { - explicit AbsoluteAddress(void* ptr) + explicit AbsoluteAddress(const void* ptr) : m_ptr(ptr) { } - void* m_ptr; + const void* m_ptr; }; - // ImmPtr: + // TrustedImmPtr: // // A pointer sized immediate operand to an instruction - this is wrapped // in a class requiring explicit construction in order to differentiate // from pointers used as absolute addresses to memory operations - struct ImmPtr { - explicit ImmPtr(const void* value) + struct TrustedImmPtr { + explicit TrustedImmPtr(const void* value) : m_value(value) { } @@ -172,14 +172,21 @@ public: const void* m_value; }; - // Imm32: + struct ImmPtr : public TrustedImmPtr { + explicit ImmPtr(const void* value) + : TrustedImmPtr(value) + { + } + }; + + // TrustedImm32: // // A 32bit immediate operand to an instruction - this is wrapped in a // class requiring explicit construction in order to prevent RegisterIDs // (which are implemented as an enum) from accidentally being passed as // immediate values. - struct Imm32 { - explicit Imm32(int32_t value) + struct TrustedImm32 { + explicit TrustedImm32(int32_t value) : m_value(value) #if CPU(ARM) || CPU(MIPS) , m_isPointer(false) @@ -188,7 +195,7 @@ public: } #if !CPU(X86_64) - explicit Imm32(ImmPtr ptr) + explicit TrustedImm32(TrustedImmPtr ptr) : m_value(ptr.asIntptr()) #if CPU(ARM) || CPU(MIPS) , m_isPointer(true) @@ -211,6 +218,19 @@ public: }; + struct Imm32 : public TrustedImm32 { + explicit Imm32(int32_t value) + : TrustedImm32(value) + { + } +#if !CPU(X86_64) + explicit Imm32(TrustedImmPtr ptr) + : TrustedImm32(ptr) + { + } +#endif + }; + // Section 2: MacroAssembler code buffer handles // // The following types are used to reference items in the code buffer @@ -358,16 +378,18 @@ public: { } - void link(AbstractMacroAssembler<AssemblerType>* masm) + void link(AbstractMacroAssembler<AssemblerType>* masm) const { masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label()); } - void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) + void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) const { masm->m_assembler.linkJump(m_jmp, label.m_label); } + bool isSet() const { return m_jmp.isSet(); } + private: JmpSrc m_jmp; }; diff --git a/Source/JavaScriptCore/assembler/AssemblerBuffer.h b/Source/JavaScriptCore/assembler/AssemblerBuffer.h index 0454a99..a90efc6 100644 --- a/Source/JavaScriptCore/assembler/AssemblerBuffer.h +++ b/Source/JavaScriptCore/assembler/AssemblerBuffer.h @@ -114,6 +114,21 @@ namespace JSC { putIntUnchecked(value); } + template<typename IntegralType> + void putIntegral(IntegralType value) + { + if (m_size > m_capacity - sizeof(IntegralType)) + grow(); + putIntegralUnchecked(value); + } + + template<typename IntegralType> + void putIntegralUnchecked(IntegralType value) + { + *reinterpret_cast_ptr<IntegralType*>(&m_buffer[m_size]) = value; + m_size += sizeof(IntegralType); + } + void* data() const { return m_buffer; diff --git a/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h b/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h index 599be14..9a9618f 100644 --- a/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h +++ b/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h @@ -188,29 +188,14 @@ public: return AssemblerBuffer::executableCopy(allocator); } - void putIntWithConstantInt(uint32_t insn, uint32_t constant, bool isReusable = false) + void putShortWithConstantInt(uint16_t insn, uint32_t constant, bool isReusable = false) { - if (!m_numConsts) - m_maxDistance = maxPoolSize; - flushIfNoSpaceFor(4, 4); - - m_loadOffsets.append(AssemblerBuffer::size()); - if (isReusable) - for (int i = 0; i < m_numConsts; ++i) { - if (m_mask[i] == ReusableConst && m_pool[i] == constant) { - AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, i)); - correctDeltas(4); - return; - } - } - - m_pool[m_numConsts] = constant; - m_mask[m_numConsts] = static_cast<char>(isReusable ? ReusableConst : UniqueConst); - - AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, m_numConsts)); - ++m_numConsts; + putIntegralWithConstantInt(insn, constant, isReusable); + } - correctDeltas(4, 4); + void putIntWithConstantInt(uint32_t insn, uint32_t constant, bool isReusable = false) + { + putIntegralWithConstantInt(insn, constant, isReusable); } // This flushing mechanism can be called after any unconditional jumps. @@ -248,6 +233,33 @@ private: m_lastConstDelta = constSize; } + template<typename IntegralType> + void putIntegralWithConstantInt(IntegralType insn, uint32_t constant, bool isReusable) + { + if (!m_numConsts) + m_maxDistance = maxPoolSize; + flushIfNoSpaceFor(sizeof(IntegralType), 4); + + m_loadOffsets.append(AssemblerBuffer::size()); + if (isReusable) { + for (int i = 0; i < m_numConsts; ++i) { + if (m_mask[i] == ReusableConst && m_pool[i] == constant) { + putIntegral(static_cast<IntegralType>(AssemblerType::patchConstantPoolLoad(insn, i))); + correctDeltas(sizeof(IntegralType)); + return; + } + } + } + + m_pool[m_numConsts] = constant; + m_mask[m_numConsts] = static_cast<char>(isReusable ? ReusableConst : UniqueConst); + + putIntegral(static_cast<IntegralType>(AssemblerType::patchConstantPoolLoad(insn, m_numConsts))); + ++m_numConsts; + + correctDeltas(sizeof(IntegralType), 4); + } + void flushConstantPool(bool useBarrier = true) { if (m_numConsts == 0) @@ -259,7 +271,7 @@ private: // Callback to protect the constant pool from execution if (useBarrier) - AssemblerBuffer::putInt(AssemblerType::placeConstantPoolBarrier(m_numConsts * sizeof(uint32_t) + alignPool)); + putIntegral(AssemblerType::placeConstantPoolBarrier(m_numConsts * sizeof(uint32_t) + alignPool)); if (alignPool) { if (alignPool & 1) diff --git a/Source/JavaScriptCore/assembler/MacroAssembler.h b/Source/JavaScriptCore/assembler/MacroAssembler.h index fa165de..bb19a98 100644 --- a/Source/JavaScriptCore/assembler/MacroAssembler.h +++ b/Source/JavaScriptCore/assembler/MacroAssembler.h @@ -74,7 +74,7 @@ public: // described in terms of other macro assembly methods. void pop() { - addPtr(Imm32(sizeof(void*)), stackPointerRegister); + addPtr(TrustedImm32(sizeof(void*)), stackPointerRegister); } void peek(RegisterID dest, int index = 0) @@ -87,19 +87,19 @@ public: storePtr(src, Address(stackPointerRegister, (index * sizeof(void*)))); } - void poke(Imm32 value, int index = 0) + void poke(TrustedImm32 value, int index = 0) { store32(value, Address(stackPointerRegister, (index * sizeof(void*)))); } - void poke(ImmPtr imm, int index = 0) + void poke(TrustedImmPtr imm, int index = 0) { storePtr(imm, Address(stackPointerRegister, (index * sizeof(void*)))); } // Backwards banches, these are currently all implemented using existing forwards branch mechanisms. - void branchPtr(Condition cond, RegisterID op1, ImmPtr imm, Label target) + void branchPtr(Condition cond, RegisterID op1, TrustedImmPtr imm, Label target) { branchPtr(cond, op1, imm).linkTo(target, this); } @@ -109,7 +109,7 @@ public: branch32(cond, op1, op2).linkTo(target, this); } - void branch32(Condition cond, RegisterID op1, Imm32 imm, Label target) + void branch32(Condition cond, RegisterID op1, TrustedImm32 imm, Label target) { branch32(cond, op1, imm).linkTo(target, this); } @@ -144,17 +144,17 @@ public: add32(src, dest); } - void addPtr(Imm32 imm, RegisterID srcDest) + void addPtr(TrustedImm32 imm, RegisterID srcDest) { add32(imm, srcDest); } - void addPtr(ImmPtr imm, RegisterID dest) + void addPtr(TrustedImmPtr imm, RegisterID dest) { - add32(Imm32(imm), dest); + add32(TrustedImm32(imm), dest); } - void addPtr(Imm32 imm, RegisterID src, RegisterID dest) + void addPtr(TrustedImm32 imm, RegisterID src, RegisterID dest) { add32(imm, src, dest); } @@ -164,7 +164,7 @@ public: and32(src, dest); } - void andPtr(Imm32 imm, RegisterID srcDest) + void andPtr(TrustedImm32 imm, RegisterID srcDest) { and32(imm, srcDest); } @@ -174,12 +174,12 @@ public: or32(src, dest); } - void orPtr(ImmPtr imm, RegisterID dest) + void orPtr(TrustedImmPtr imm, RegisterID dest) { - or32(Imm32(imm), dest); + or32(TrustedImm32(imm), dest); } - void orPtr(Imm32 imm, RegisterID dest) + void orPtr(TrustedImm32 imm, RegisterID dest) { or32(imm, dest); } @@ -189,14 +189,14 @@ public: sub32(src, dest); } - void subPtr(Imm32 imm, RegisterID dest) + void subPtr(TrustedImm32 imm, RegisterID dest) { sub32(imm, dest); } - void subPtr(ImmPtr imm, RegisterID dest) + void subPtr(TrustedImmPtr imm, RegisterID dest) { - sub32(Imm32(imm), dest); + sub32(TrustedImm32(imm), dest); } void xorPtr(RegisterID src, RegisterID dest) @@ -204,7 +204,7 @@ public: xor32(src, dest); } - void xorPtr(Imm32 imm, RegisterID srcDest) + void xorPtr(TrustedImm32 imm, RegisterID srcDest) { xor32(imm, srcDest); } @@ -230,7 +230,7 @@ public: return load32WithAddressOffsetPatch(address, dest); } - void setPtr(Condition cond, RegisterID left, Imm32 right, RegisterID dest) + void setPtr(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest) { set32Compare32(cond, left, right, dest); } @@ -250,14 +250,14 @@ public: store32(src, address); } - void storePtr(ImmPtr imm, ImplicitAddress address) + void storePtr(TrustedImmPtr imm, ImplicitAddress address) { - store32(Imm32(imm), address); + store32(TrustedImm32(imm), address); } - void storePtr(ImmPtr imm, void* address) + void storePtr(TrustedImmPtr imm, void* address) { - store32(Imm32(imm), address); + store32(TrustedImm32(imm), address); } DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address) @@ -271,9 +271,9 @@ public: return branch32(cond, left, right); } - Jump branchPtr(Condition cond, RegisterID left, ImmPtr right) + Jump branchPtr(Condition cond, RegisterID left, TrustedImmPtr right) { - return branch32(cond, left, Imm32(right)); + return branch32(cond, left, TrustedImm32(right)); } Jump branchPtr(Condition cond, RegisterID left, Address right) @@ -291,14 +291,14 @@ public: return branch32(cond, left, right); } - Jump branchPtr(Condition cond, Address left, ImmPtr right) + Jump branchPtr(Condition cond, Address left, TrustedImmPtr right) { - return branch32(cond, left, Imm32(right)); + return branch32(cond, left, TrustedImm32(right)); } - Jump branchPtr(Condition cond, AbsoluteAddress left, ImmPtr right) + Jump branchPtr(Condition cond, AbsoluteAddress left, TrustedImmPtr right) { - return branch32(cond, left, Imm32(right)); + return branch32(cond, left, TrustedImm32(right)); } Jump branchTestPtr(Condition cond, RegisterID reg, RegisterID mask) @@ -306,17 +306,17 @@ public: return branchTest32(cond, reg, mask); } - Jump branchTestPtr(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1)) + Jump branchTestPtr(Condition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) { return branchTest32(cond, reg, mask); } - Jump branchTestPtr(Condition cond, Address address, Imm32 mask = Imm32(-1)) + Jump branchTestPtr(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { return branchTest32(cond, address, mask); } - Jump branchTestPtr(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1)) + Jump branchTestPtr(Condition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { return branchTest32(cond, address, mask); } @@ -327,12 +327,12 @@ public: return branchAdd32(cond, src, dest); } - Jump branchSubPtr(Condition cond, Imm32 imm, RegisterID dest) + Jump branchSubPtr(Condition cond, TrustedImm32 imm, RegisterID dest) { return branchSub32(cond, imm, dest); } using MacroAssemblerBase::branchTest8; - Jump branchTest8(Condition cond, ExtendedAddress address, Imm32 mask = Imm32(-1)) + Jump branchTest8(Condition cond, ExtendedAddress address, TrustedImm32 mask = TrustedImm32(-1)) { return MacroAssemblerBase::branchTest8(cond, Address(address.base, address.offset), mask); } diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h index 66814b5..80f69bf 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h @@ -86,14 +86,14 @@ public: m_assembler.adds_r(dest, dest, src); } - void add32(Imm32 imm, Address address) + void add32(TrustedImm32 imm, Address address) { load32(address, ARMRegisters::S1); add32(imm, ARMRegisters::S1); store32(ARMRegisters::S1, address); } - void add32(Imm32 imm, RegisterID dest) + void add32(TrustedImm32 imm, RegisterID dest) { m_assembler.adds_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); } @@ -109,7 +109,7 @@ public: m_assembler.ands_r(dest, dest, src); } - void and32(Imm32 imm, RegisterID dest) + void and32(TrustedImm32 imm, RegisterID dest) { ARMWord w = m_assembler.getImm(imm.m_value, ARMRegisters::S0, true); if (w & ARMAssembler::OP2_INV_IMM) @@ -127,7 +127,7 @@ public: m_assembler.movs_r(dest, m_assembler.lsl_r(dest, ARMRegisters::S0)); } - void lshift32(Imm32 imm, RegisterID dest) + void lshift32(TrustedImm32 imm, RegisterID dest) { m_assembler.movs_r(dest, m_assembler.lsl(dest, imm.m_value & 0x1f)); } @@ -141,7 +141,7 @@ public: m_assembler.muls_r(dest, dest, src); } - void mul32(Imm32 imm, RegisterID src, RegisterID dest) + void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest) { move(imm, ARMRegisters::S0); m_assembler.muls_r(dest, src, ARMRegisters::S0); @@ -162,7 +162,7 @@ public: m_assembler.orrs_r(dest, dest, src); } - void or32(Imm32 imm, RegisterID dest) + void or32(TrustedImm32 imm, RegisterID dest) { m_assembler.orrs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); } @@ -176,7 +176,7 @@ public: m_assembler.movs_r(dest, m_assembler.asr_r(dest, ARMRegisters::S0)); } - void rshift32(Imm32 imm, RegisterID dest) + void rshift32(TrustedImm32 imm, RegisterID dest) { m_assembler.movs_r(dest, m_assembler.asr(dest, imm.m_value & 0x1f)); } @@ -190,7 +190,7 @@ public: m_assembler.movs_r(dest, m_assembler.lsr_r(dest, ARMRegisters::S0)); } - void urshift32(Imm32 imm, RegisterID dest) + void urshift32(TrustedImm32 imm, RegisterID dest) { m_assembler.movs_r(dest, m_assembler.lsr(dest, imm.m_value & 0x1f)); } @@ -200,12 +200,12 @@ public: m_assembler.subs_r(dest, dest, src); } - void sub32(Imm32 imm, RegisterID dest) + void sub32(TrustedImm32 imm, RegisterID dest) { m_assembler.subs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); } - void sub32(Imm32 imm, Address address) + void sub32(TrustedImm32 imm, Address address) { load32(address, ARMRegisters::S1); sub32(imm, ARMRegisters::S1); @@ -223,7 +223,7 @@ public: m_assembler.eors_r(dest, dest, src); } - void xor32(Imm32 imm, RegisterID dest) + void xor32(TrustedImm32 imm, RegisterID dest) { m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); } @@ -303,7 +303,7 @@ public: m_assembler.baseIndexTransfer32(false, src, address.base, address.index, static_cast<int>(address.scale), address.offset); } - void store32(Imm32 imm, ImplicitAddress address) + void store32(TrustedImm32 imm, ImplicitAddress address) { if (imm.m_isPointer) m_assembler.ldr_un_imm(ARMRegisters::S1, imm.m_value); @@ -318,7 +318,7 @@ public: m_assembler.dtr_u(false, src, ARMRegisters::S0, 0); } - void store32(Imm32 imm, void* address) + void store32(TrustedImm32 imm, void* address) { m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address)); if (imm.m_isPointer) @@ -344,13 +344,13 @@ public: push(ARMRegisters::S1); } - void push(Imm32 imm) + void push(TrustedImm32 imm) { move(imm, ARMRegisters::S0); push(ARMRegisters::S0); } - void move(Imm32 imm, RegisterID dest) + void move(TrustedImm32 imm, RegisterID dest) { if (imm.m_isPointer) m_assembler.ldr_un_imm(dest, imm.m_value); @@ -363,9 +363,9 @@ public: m_assembler.mov_r(dest, src); } - void move(ImmPtr imm, RegisterID dest) + void move(TrustedImmPtr imm, RegisterID dest) { - move(Imm32(imm), dest); + move(TrustedImm32(imm), dest); } void swap(RegisterID reg1, RegisterID reg2) @@ -387,7 +387,7 @@ public: move(src, dest); } - Jump branch8(Condition cond, Address left, Imm32 right) + Jump branch8(Condition cond, Address left, TrustedImm32 right) { load8(left, ARMRegisters::S1); return branch32(cond, ARMRegisters::S1, right); @@ -399,7 +399,7 @@ public: return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool)); } - Jump branch32(Condition cond, RegisterID left, Imm32 right, int useConstantPool = 0) + Jump branch32(Condition cond, RegisterID left, TrustedImm32 right, int useConstantPool = 0) { if (right.m_isPointer) { m_assembler.ldr_un_imm(ARMRegisters::S0, right.m_value); @@ -426,19 +426,19 @@ public: return branch32(cond, ARMRegisters::S1, right); } - Jump branch32(Condition cond, Address left, Imm32 right) + Jump branch32(Condition cond, Address left, TrustedImm32 right) { load32(left, ARMRegisters::S1); return branch32(cond, ARMRegisters::S1, right); } - Jump branch32(Condition cond, BaseIndex left, Imm32 right) + Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right) { load32(left, ARMRegisters::S1); return branch32(cond, ARMRegisters::S1, right); } - Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right) + Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right) { load32WithUnalignedHalfWords(left, ARMRegisters::S1); return branch32(cond, ARMRegisters::S1, right); @@ -453,7 +453,7 @@ public: return jump(); } - Jump branch16(Condition cond, BaseIndex left, Imm32 right) + Jump branch16(Condition cond, BaseIndex left, TrustedImm32 right) { load16(left, ARMRegisters::S0); move(right, ARMRegisters::S1); @@ -461,7 +461,7 @@ public: return m_assembler.jmp(ARMCondition(cond)); } - Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1)) + Jump branchTest8(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { load8(address, ARMRegisters::S1); return branchTest32(cond, ARMRegisters::S1, mask); @@ -474,7 +474,7 @@ public: return Jump(m_assembler.jmp(ARMCondition(cond))); } - Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1)) + Jump branchTest32(Condition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) { ASSERT((cond == Zero) || (cond == NonZero)); ARMWord w = m_assembler.getImm(mask.m_value, ARMRegisters::S0, true); @@ -485,13 +485,13 @@ public: return Jump(m_assembler.jmp(ARMCondition(cond))); } - Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1)) + Jump branchTest32(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { load32(address, ARMRegisters::S1); return branchTest32(cond, ARMRegisters::S1, mask); } - Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1)) + Jump branchTest32(Condition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { load32(address, ARMRegisters::S1); return branchTest32(cond, ARMRegisters::S1, mask); @@ -519,7 +519,7 @@ public: return Jump(m_assembler.jmp(ARMCondition(cond))); } - Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest) + Jump branchAdd32(Condition cond, TrustedImm32 imm, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); add32(imm, dest); @@ -548,7 +548,7 @@ public: return Jump(m_assembler.jmp(ARMCondition(cond))); } - Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest) + Jump branchMul32(Condition cond, TrustedImm32 imm, RegisterID src, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); if (cond == Overflow) { @@ -568,7 +568,7 @@ public: return Jump(m_assembler.jmp(ARMCondition(cond))); } - Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest) + Jump branchSub32(Condition cond, TrustedImm32 imm, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); sub32(imm, dest); @@ -628,7 +628,7 @@ public: m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond)); } - void set32Compare32(Condition cond, RegisterID left, Imm32 right, RegisterID dest) + void set32Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest) { m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0)); m_assembler.mov_r(dest, ARMAssembler::getOp2(0)); @@ -648,13 +648,13 @@ public: set32Compare32(cond, ARMRegisters::S1, right, dest); } - void set8Compare32(Condition cond, RegisterID left, Imm32 right, RegisterID dest) + void set8Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest) { // ARM doesn't have byte registers set32Compare32(cond, left, right, dest); } - void set32Test32(Condition cond, RegisterID reg, Imm32 mask, RegisterID dest) + void set32Test32(Condition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest) { if (mask.m_value == -1) m_assembler.cmp_r(0, reg); @@ -664,24 +664,24 @@ public: m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond)); } - void set32Test32(Condition cond, Address address, Imm32 mask, RegisterID dest) + void set32Test32(Condition cond, Address address, TrustedImm32 mask, RegisterID dest) { load32(address, ARMRegisters::S1); set32Test32(cond, ARMRegisters::S1, mask, dest); } - void set32Test8(Condition cond, Address address, Imm32 mask, RegisterID dest) + void set32Test8(Condition cond, Address address, TrustedImm32 mask, RegisterID dest) { load8(address, ARMRegisters::S1); set32Test32(cond, ARMRegisters::S1, mask, dest); } - void add32(Imm32 imm, RegisterID src, RegisterID dest) + void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) { m_assembler.add_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); } - void add32(Imm32 imm, AbsoluteAddress address) + void add32(TrustedImm32 imm, AbsoluteAddress address) { m_assembler.ldr_un_imm(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr)); m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0); @@ -690,7 +690,7 @@ public: m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0); } - void sub32(Imm32 imm, AbsoluteAddress address) + void sub32(TrustedImm32 imm, AbsoluteAddress address) { m_assembler.ldr_un_imm(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr)); m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0); @@ -699,7 +699,7 @@ public: m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0); } - void load32(void* address, RegisterID dest) + void load32(const void* address, RegisterID dest) { m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address)); m_assembler.dtr_u(true, dest, ARMRegisters::S0, 0); @@ -711,7 +711,7 @@ public: return branch32(cond, ARMRegisters::S1, right); } - Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right) + Jump branch32(Condition cond, AbsoluteAddress left, TrustedImm32 right) { load32(left.m_ptr, ARMRegisters::S1); return branch32(cond, ARMRegisters::S1, right); @@ -748,21 +748,21 @@ public: return Call::fromTailJump(oldJump); } - DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest) + DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest) { DataLabelPtr dataLabel(this); m_assembler.ldr_un_imm(dest, reinterpret_cast<ARMWord>(initialValue.m_value)); return dataLabel; } - Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0)) + Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S1); Jump jump = branch32(cond, left, ARMRegisters::S1, true); return jump; } - Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0)) + Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { load32(left, ARMRegisters::S1); dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S0); @@ -770,7 +770,7 @@ public: return jump; } - DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address) + DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address) { DataLabelPtr dataLabel = moveWithPatch(initialValue, ARMRegisters::S1); store32(ARMRegisters::S1, address); @@ -779,7 +779,7 @@ public: DataLabelPtr storePtrWithPatch(ImplicitAddress address) { - return storePtrWithPatch(ImmPtr(0), address); + return storePtrWithPatch(TrustedImmPtr(0), address); } // Floating point operators diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h index 450a34c..84e0a5e 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h @@ -139,7 +139,7 @@ public: // Integer arithmetic operations: // // Operations are typically two operand - operation(source, srcDst) - // For many operations the source may be an Imm32, the srcDst operand + // For many operations the source may be an TrustedImm32, the srcDst operand // may often be a memory location (explictly described using an Address // object). @@ -148,12 +148,12 @@ public: m_assembler.add(dest, dest, src); } - void add32(Imm32 imm, RegisterID dest) + void add32(TrustedImm32 imm, RegisterID dest) { add32(imm, dest, dest); } - void add32(Imm32 imm, RegisterID src, RegisterID dest) + void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) { ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12OrEncodedImm(imm.m_value); if (armImm.isValid()) @@ -164,7 +164,7 @@ public: } } - void add32(Imm32 imm, Address address) + void add32(TrustedImm32 imm, Address address) { load32(address, dataTempRegister); @@ -187,7 +187,7 @@ public: add32(dataTempRegister, dest); } - void add32(Imm32 imm, AbsoluteAddress address) + void add32(TrustedImm32 imm, AbsoluteAddress address) { load32(address.m_ptr, dataTempRegister); @@ -209,7 +209,7 @@ public: m_assembler.ARM_and(dest, dest, src); } - void and32(Imm32 imm, RegisterID dest) + void and32(TrustedImm32 imm, RegisterID dest) { ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value); if (armImm.isValid()) @@ -235,7 +235,7 @@ public: m_assembler.lsl(dest, dest, dataTempRegister); } - void lshift32(Imm32 imm, RegisterID dest) + void lshift32(TrustedImm32 imm, RegisterID dest) { m_assembler.lsl(dest, dest, imm.m_value & 0x1f); } @@ -245,7 +245,7 @@ public: m_assembler.smull(dest, dataTempRegister, dest, src); } - void mul32(Imm32 imm, RegisterID src, RegisterID dest) + void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest) { move(imm, dataTempRegister); m_assembler.smull(dest, dataTempRegister, src, dataTempRegister); @@ -266,7 +266,7 @@ public: m_assembler.orr(dest, dest, src); } - void or32(Imm32 imm, RegisterID dest) + void or32(TrustedImm32 imm, RegisterID dest) { ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value); if (armImm.isValid()) @@ -287,7 +287,7 @@ public: m_assembler.asr(dest, dest, dataTempRegister); } - void rshift32(Imm32 imm, RegisterID dest) + void rshift32(TrustedImm32 imm, RegisterID dest) { m_assembler.asr(dest, dest, imm.m_value & 0x1f); } @@ -302,7 +302,7 @@ public: m_assembler.lsr(dest, dest, dataTempRegister); } - void urshift32(Imm32 imm, RegisterID dest) + void urshift32(TrustedImm32 imm, RegisterID dest) { m_assembler.lsr(dest, dest, imm.m_value & 0x1f); } @@ -312,7 +312,7 @@ public: m_assembler.sub(dest, dest, src); } - void sub32(Imm32 imm, RegisterID dest) + void sub32(TrustedImm32 imm, RegisterID dest) { ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12OrEncodedImm(imm.m_value); if (armImm.isValid()) @@ -323,7 +323,7 @@ public: } } - void sub32(Imm32 imm, Address address) + void sub32(TrustedImm32 imm, Address address) { load32(address, dataTempRegister); @@ -346,7 +346,7 @@ public: sub32(dataTempRegister, dest); } - void sub32(Imm32 imm, AbsoluteAddress address) + void sub32(TrustedImm32 imm, AbsoluteAddress address) { load32(address.m_ptr, dataTempRegister); @@ -368,7 +368,7 @@ public: m_assembler.eor(dest, dest, src); } - void xor32(Imm32 imm, RegisterID dest) + void xor32(TrustedImm32 imm, RegisterID dest) { ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value); if (armImm.isValid()) @@ -383,7 +383,7 @@ public: // Memory access operations: // // Loads are of the form load(address, destination) and stores of the form - // store(source, address). The source for a store may be an Imm32. Address + // store(source, address). The source for a store may be an TrustedImm32. Address // operand objects to loads and store will be implicitly constructed if a // register is passed. @@ -460,9 +460,9 @@ public: load32(setupArmAddress(address), dest); } - void load32(void* address, RegisterID dest) + void load32(const void* address, RegisterID dest) { - move(ImmPtr(address), addressTempRegister); + move(TrustedImmPtr(address), addressTempRegister); m_assembler.ldr(dest, addressTempRegister, ARMThumbImmediate::makeUInt16(0)); } @@ -473,7 +473,7 @@ public: DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest) { - DataLabel32 label = moveWithPatch(Imm32(address.offset), dataTempRegister); + DataLabel32 label = moveWithPatch(TrustedImm32(address.offset), dataTempRegister); load32(ArmAddress(address.base, dataTempRegister), dest); return label; } @@ -489,14 +489,14 @@ public: if (armImm.isValid()) m_assembler.ldrh(dest, address.base, armImm); else { - move(Imm32(address.offset), dataTempRegister); + move(TrustedImm32(address.offset), dataTempRegister); m_assembler.ldrh(dest, address.base, dataTempRegister); } } DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address) { - DataLabel32 label = moveWithPatch(Imm32(address.offset), dataTempRegister); + DataLabel32 label = moveWithPatch(TrustedImm32(address.offset), dataTempRegister); store32(src, ArmAddress(address.base, dataTempRegister)); return label; } @@ -511,19 +511,19 @@ public: store32(src, setupArmAddress(address)); } - void store32(Imm32 imm, ImplicitAddress address) + void store32(TrustedImm32 imm, ImplicitAddress address) { move(imm, dataTempRegister); store32(dataTempRegister, setupArmAddress(address)); } - void store32(RegisterID src, void* address) + void store32(RegisterID src, const void* address) { - move(ImmPtr(address), addressTempRegister); + move(TrustedImmPtr(address), addressTempRegister); m_assembler.str(src, addressTempRegister, ARMThumbImmediate::makeUInt16(0)); } - void store32(Imm32 imm, void* address) + void store32(TrustedImm32 imm, const void* address) { move(imm, dataTempRegister); store32(dataTempRegister, address); @@ -558,7 +558,7 @@ public: // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2. if ((offset & 3) || (offset > (255 * 4)) || (offset < -(255 * 4))) { - add32(Imm32(offset), base, addressTempRegister); + add32(TrustedImm32(offset), base, addressTempRegister); base = addressTempRegister; offset = 0; } @@ -568,7 +568,7 @@ public: void loadDouble(const void* address, FPRegisterID dest) { - move(ImmPtr(address), addressTempRegister); + move(TrustedImmPtr(address), addressTempRegister); m_assembler.vldr(dest, addressTempRegister, 0); } @@ -579,7 +579,7 @@ public: // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2. if ((offset & 3) || (offset > (255 * 4)) || (offset < -(255 * 4))) { - add32(Imm32(offset), base, addressTempRegister); + add32(TrustedImm32(offset), base, addressTempRegister); base = addressTempRegister; offset = 0; } @@ -748,7 +748,7 @@ public: push(dataTempRegister); } - void push(Imm32 imm) + void push(TrustedImm32 imm) { move(imm, dataTempRegister); push(dataTempRegister); @@ -758,7 +758,7 @@ public: // // Move values in registers. - void move(Imm32 imm, RegisterID dest) + void move(TrustedImm32 imm, RegisterID dest) { uint32_t value = imm.m_value; @@ -784,9 +784,9 @@ public: m_assembler.mov(dest, src); } - void move(ImmPtr imm, RegisterID dest) + void move(TrustedImmPtr imm, RegisterID dest) { - move(Imm32(imm), dest); + move(TrustedImm32(imm), dest); } void swap(RegisterID reg1, RegisterID reg2) @@ -821,7 +821,7 @@ public: // used (representing the names 'below' and 'above'). // // Operands to the comparision are provided in the expected order, e.g. - // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when + // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when // treated as a signed 32bit value, is less than or equal to 5. // // jz and jnz test whether the first operand is equal to zero, and take @@ -829,7 +829,7 @@ public: private: // Should we be using TEQ for equal/not-equal? - void compare32(RegisterID left, Imm32 right) + void compare32(RegisterID left, TrustedImm32 right) { int32_t imm = right.m_value; if (!imm) @@ -841,13 +841,13 @@ private: else if ((armImm = ARMThumbImmediate::makeEncodedImm(-imm)).isValid()) m_assembler.cmn(left, armImm); else { - move(Imm32(imm), dataTempRegister); + move(TrustedImm32(imm), dataTempRegister); m_assembler.cmp(left, dataTempRegister); } } } - void test32(RegisterID reg, Imm32 mask) + void test32(RegisterID reg, TrustedImm32 mask) { int32_t imm = mask.m_value; @@ -871,7 +871,7 @@ public: return Jump(makeBranch(cond)); } - Jump branch32(Condition cond, RegisterID left, Imm32 right) + Jump branch32(Condition cond, RegisterID left, TrustedImm32 right) { compare32(left, right); return Jump(makeBranch(cond)); @@ -889,21 +889,21 @@ public: return branch32(cond, dataTempRegister, right); } - Jump branch32(Condition cond, Address left, Imm32 right) + Jump branch32(Condition cond, Address left, TrustedImm32 right) { // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/ load32(left, addressTempRegister); return branch32(cond, addressTempRegister, right); } - Jump branch32(Condition cond, BaseIndex left, Imm32 right) + Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right) { // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/ load32(left, addressTempRegister); return branch32(cond, addressTempRegister, right); } - Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right) + Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right) { // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/ load32WithUnalignedHalfWords(left, addressTempRegister); @@ -916,7 +916,7 @@ public: return branch32(cond, dataTempRegister, right); } - Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right) + Jump branch32(Condition cond, AbsoluteAddress left, TrustedImm32 right) { // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/ load32(left.m_ptr, addressTempRegister); @@ -931,21 +931,21 @@ public: return branch32(cond, dataTempRegister, addressTempRegister); } - Jump branch16(Condition cond, BaseIndex left, Imm32 right) + Jump branch16(Condition cond, BaseIndex left, TrustedImm32 right) { // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/ load16(left, addressTempRegister); m_assembler.lsl(addressTempRegister, addressTempRegister, 16); - return branch32(cond, addressTempRegister, Imm32(right.m_value << 16)); + return branch32(cond, addressTempRegister, TrustedImm32(right.m_value << 16)); } - Jump branch8(Condition cond, RegisterID left, Imm32 right) + Jump branch8(Condition cond, RegisterID left, TrustedImm32 right) { compare32(left, right); return Jump(makeBranch(cond)); } - Jump branch8(Condition cond, Address left, Imm32 right) + Jump branch8(Condition cond, Address left, TrustedImm32 right) { // use addressTempRegister incase the branch8 we call uses dataTempRegister. :-/ load8(left, addressTempRegister); @@ -959,14 +959,14 @@ public: return Jump(makeBranch(cond)); } - Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1)) + Jump branchTest32(Condition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) { ASSERT((cond == Zero) || (cond == NonZero)); test32(reg, mask); return Jump(makeBranch(cond)); } - Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1)) + Jump branchTest32(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { ASSERT((cond == Zero) || (cond == NonZero)); // use addressTempRegister incase the branchTest32 we call uses dataTempRegister. :-/ @@ -974,7 +974,7 @@ public: return branchTest32(cond, addressTempRegister, mask); } - Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1)) + Jump branchTest32(Condition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { ASSERT((cond == Zero) || (cond == NonZero)); // use addressTempRegister incase the branchTest32 we call uses dataTempRegister. :-/ @@ -982,14 +982,14 @@ public: return branchTest32(cond, addressTempRegister, mask); } - Jump branchTest8(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1)) + Jump branchTest8(Condition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) { ASSERT((cond == Zero) || (cond == NonZero)); test32(reg, mask); return Jump(makeBranch(cond)); } - Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1)) + Jump branchTest8(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { ASSERT((cond == Zero) || (cond == NonZero)); // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/ @@ -1032,7 +1032,7 @@ public: return Jump(makeBranch(cond)); } - Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest) + Jump branchAdd32(Condition cond, TrustedImm32 imm, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value); @@ -1053,7 +1053,7 @@ public: return branch32(NotEqual, addressTempRegister, dataTempRegister); } - Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest) + Jump branchMul32(Condition cond, TrustedImm32 imm, RegisterID src, RegisterID dest) { ASSERT_UNUSED(cond, cond == Overflow); move(imm, dataTempRegister); @@ -1076,7 +1076,7 @@ public: return Jump(makeBranch(cond)); } - Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest) + Jump branchSub32(Condition cond, TrustedImm32 imm, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value); @@ -1111,13 +1111,13 @@ public: Call nearCall() { - moveFixedWidthEncoding(Imm32(0), dataTempRegister); + moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister); return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::LinkableNear); } Call call() { - moveFixedWidthEncoding(Imm32(0), dataTempRegister); + moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister); return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::Linkable); } @@ -1151,7 +1151,7 @@ public: set32Compare32(cond, dataTempRegister, right, dest); } - void set32Compare32(Condition cond, RegisterID left, Imm32 right, RegisterID dest) + void set32Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest) { compare32(left, right); m_assembler.it(armV7Condition(cond), false); @@ -1169,7 +1169,7 @@ public: set32Compare32(cond, left, right, dest); } - void set8Compare32(Condition cond, RegisterID left, Imm32 right, RegisterID dest) + void set8Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest) { set32Compare32(cond, left, right, dest); } @@ -1178,7 +1178,7 @@ public: // The mask should be optional... paerhaps the argument order should be // dest-src, operations always have a dest? ... possibly not true, considering // asm ops like test, or pseudo ops like pop(). - void set32Test32(Condition cond, Address address, Imm32 mask, RegisterID dest) + void set32Test32(Condition cond, Address address, TrustedImm32 mask, RegisterID dest) { load32(address, dataTempRegister); test32(dataTempRegister, mask); @@ -1187,7 +1187,7 @@ public: m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0)); } - void set32Test8(Condition cond, Address address, Imm32 mask, RegisterID dest) + void set32Test8(Condition cond, Address address, TrustedImm32 mask, RegisterID dest) { load8(address, dataTempRegister); test32(dataTempRegister, mask); @@ -1196,44 +1196,44 @@ public: m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0)); } - DataLabel32 moveWithPatch(Imm32 imm, RegisterID dst) + DataLabel32 moveWithPatch(TrustedImm32 imm, RegisterID dst) { moveFixedWidthEncoding(imm, dst); return DataLabel32(this); } - DataLabelPtr moveWithPatch(ImmPtr imm, RegisterID dst) + DataLabelPtr moveWithPatch(TrustedImmPtr imm, RegisterID dst) { - moveFixedWidthEncoding(Imm32(imm), dst); + moveFixedWidthEncoding(TrustedImm32(imm), dst); return DataLabelPtr(this); } - Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0)) + Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { dataLabel = moveWithPatch(initialRightValue, dataTempRegister); return branch32(cond, left, dataTempRegister); } - Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0)) + Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { load32(left, addressTempRegister); dataLabel = moveWithPatch(initialRightValue, dataTempRegister); return branch32(cond, addressTempRegister, dataTempRegister); } - DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address) + DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address) { DataLabelPtr label = moveWithPatch(initialValue, dataTempRegister); store32(dataTempRegister, address); return label; } - DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(ImmPtr(0), address); } + DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(TrustedImmPtr(0), address); } Call tailRecursiveCall() { // Like a normal call, but don't link. - moveFixedWidthEncoding(Imm32(0), dataTempRegister); + moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister); return Call(m_assembler.bx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::Linkable); } @@ -1257,14 +1257,14 @@ protected: ARMv7Assembler::JmpSrc makeJump() { - moveFixedWidthEncoding(Imm32(0), dataTempRegister); + moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister); return m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpNoConditionFixedSize : ARMv7Assembler::JumpNoCondition); } ARMv7Assembler::JmpSrc makeBranch(ARMv7Assembler::Condition cond) { m_assembler.it(cond, true, true); - moveFixedWidthEncoding(Imm32(0), dataTempRegister); + moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister); return m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpConditionFixedSize : ARMv7Assembler::JumpCondition, cond); } ARMv7Assembler::JmpSrc makeBranch(Condition cond) { return makeBranch(armV7Condition(cond)); } @@ -1277,7 +1277,7 @@ protected: if (imm.isValid()) m_assembler.add(addressTempRegister, address.base, imm); else { - move(Imm32(address.offset), addressTempRegister); + move(TrustedImm32(address.offset), addressTempRegister); m_assembler.add(addressTempRegister, addressTempRegister, address.base); } @@ -1291,7 +1291,7 @@ protected: if ((address.offset >= -0xff) && (address.offset <= 0xfff)) return ArmAddress(address.base, address.offset); - move(Imm32(address.offset), addressTempRegister); + move(TrustedImm32(address.offset), addressTempRegister); return ArmAddress(address.base, addressTempRegister); } @@ -1300,7 +1300,7 @@ protected: if ((address.offset >= -0xff) && (address.offset <= 0xfff)) return ArmAddress(address.base, address.offset); - move(Imm32(address.offset), addressTempRegister); + move(TrustedImm32(address.offset), addressTempRegister); return ArmAddress(address.base, addressTempRegister); } @@ -1313,14 +1313,14 @@ protected: if (imm.isValid()) m_assembler.add(addressTempRegister, address.base, imm); else { - move(Imm32(address.offset), addressTempRegister); + move(TrustedImm32(address.offset), addressTempRegister); m_assembler.add(addressTempRegister, addressTempRegister, address.base); } return addressTempRegister; } - void moveFixedWidthEncoding(Imm32 imm, RegisterID dst) + void moveFixedWidthEncoding(TrustedImm32 imm, RegisterID dst) { uint32_t value = imm.m_value; m_assembler.movT3(dst, ARMThumbImmediate::makeUInt16(value & 0xffff)); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h b/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h index 543b0fa..2183b22 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h @@ -65,15 +65,47 @@ public: { } + template<typename returnType> + FunctionPtr(returnType(*value)()) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template<typename returnType, typename argType1> + FunctionPtr(returnType(*value)(argType1)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template<typename returnType, typename argType1, typename argType2> + FunctionPtr(returnType(*value)(argType1, argType2)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template<typename returnType, typename argType1, typename argType2, typename argType3> + FunctionPtr(returnType(*value)(argType1, argType2, argType3)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template<typename returnType, typename argType1, typename argType2, typename argType3, typename argType4> + FunctionPtr(returnType(*value)(argType1, argType2, argType3, argType4)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + template<typename FunctionType> explicit FunctionPtr(FunctionType* value) -#if COMPILER(RVCT) - // RVTC compiler needs C-style cast as it fails with the following error - // Error: #694: reinterpret_cast cannot cast away const or other type qualifiers - : m_value((void*)(value)) -#else - : m_value(reinterpret_cast<void*>(value)) -#endif + // Using a C-ctyle cast here to avoid compiler error on RVTC: + // Error: #694: reinterpret_cast cannot cast away const or other type qualifiers + // (I guess on RVTC function pointers have a different constness to GCC/MSVC?) + : m_value((void*)value) { ASSERT_VALID_CODE_POINTER(m_value); } diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h index 4697dfc..1bcec38 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h @@ -95,7 +95,7 @@ public: // Integer arithmetic operations: // // Operations are typically two operand - operation(source, srcDst) - // For many operations the source may be an Imm32, the srcDst operand + // For many operations the source may be an TrustedImm32, the srcDst operand // may often be a memory location (explictly described using an Address // object). @@ -104,12 +104,12 @@ public: m_assembler.addu(dest, dest, src); } - void add32(Imm32 imm, RegisterID dest) + void add32(TrustedImm32 imm, RegisterID dest) { add32(imm, dest, dest); } - void add32(Imm32 imm, RegisterID src, RegisterID dest) + void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) { if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) { @@ -127,7 +127,7 @@ public: } } - void add32(Imm32 imm, Address address) + void add32(TrustedImm32 imm, Address address) { if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) { @@ -207,7 +207,7 @@ public: } } - void add32(Imm32 imm, AbsoluteAddress address) + void add32(TrustedImm32 imm, AbsoluteAddress address) { /* li addrTemp, address @@ -216,7 +216,7 @@ public: addu dataTemp, dataTemp, immTemp sw dataTemp, 0(addrTemp) */ - move(ImmPtr(address.m_ptr), addrTempRegister); + move(TrustedImmPtr(address.m_ptr), addrTempRegister); m_assembler.lw(dataTempRegister, addrTempRegister, 0); if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) @@ -233,7 +233,7 @@ public: m_assembler.andInsn(dest, dest, src); } - void and32(Imm32 imm, RegisterID dest) + void and32(TrustedImm32 imm, RegisterID dest) { if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) move(MIPSRegisters::zero, dest); @@ -250,7 +250,7 @@ public: } } - void lshift32(Imm32 imm, RegisterID dest) + void lshift32(TrustedImm32 imm, RegisterID dest) { m_assembler.sll(dest, dest, imm.m_value); } @@ -265,7 +265,7 @@ public: m_assembler.mul(dest, dest, src); } - void mul32(Imm32 imm, RegisterID src, RegisterID dest) + void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest) { if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) move(MIPSRegisters::zero, dest); @@ -296,7 +296,7 @@ public: m_assembler.orInsn(dest, dest, src); } - void or32(Imm32 imm, RegisterID dest) + void or32(TrustedImm32 imm, RegisterID dest) { if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) return; @@ -320,7 +320,7 @@ public: m_assembler.srav(dest, dest, shiftAmount); } - void rshift32(Imm32 imm, RegisterID dest) + void rshift32(TrustedImm32 imm, RegisterID dest) { m_assembler.sra(dest, dest, imm.m_value); } @@ -330,7 +330,7 @@ public: m_assembler.srlv(dest, dest, shiftAmount); } - void urshift32(Imm32 imm, RegisterID dest) + void urshift32(TrustedImm32 imm, RegisterID dest) { m_assembler.srl(dest, dest, imm.m_value); } @@ -340,7 +340,7 @@ public: m_assembler.subu(dest, dest, src); } - void sub32(Imm32 imm, RegisterID dest) + void sub32(TrustedImm32 imm, RegisterID dest) { if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth) { @@ -358,7 +358,7 @@ public: } } - void sub32(Imm32 imm, Address address) + void sub32(TrustedImm32 imm, Address address) { if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) { @@ -413,7 +413,7 @@ public: sub32(dataTempRegister, dest); } - void sub32(Imm32 imm, AbsoluteAddress address) + void sub32(TrustedImm32 imm, AbsoluteAddress address) { /* li addrTemp, address @@ -422,7 +422,7 @@ public: subu dataTemp, dataTemp, immTemp sw dataTemp, 0(addrTemp) */ - move(ImmPtr(address.m_ptr), addrTempRegister); + move(TrustedImmPtr(address.m_ptr), addrTempRegister); m_assembler.lw(dataTempRegister, addrTempRegister, 0); if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768 @@ -441,7 +441,7 @@ public: m_assembler.xorInsn(dest, dest, src); } - void xor32(Imm32 imm, RegisterID dest) + void xor32(TrustedImm32 imm, RegisterID dest) { /* li immTemp, imm @@ -459,7 +459,7 @@ public: // Memory access operations: // // Loads are of the form load(address, destination) and stores of the form - // store(source, address). The source for a store may be an Imm32. Address + // store(source, address). The source for a store may be an TrustedImm32. Address // operand objects to loads and store will be implicitly constructed if a // register is passed. @@ -581,13 +581,13 @@ public: } } - void load32(void* address, RegisterID dest) + void load32(const void* address, RegisterID dest) { /* li addrTemp, address lw dest, 0(addrTemp) */ - move(ImmPtr(address), addrTempRegister); + move(TrustedImmPtr(address), addrTempRegister); m_assembler.lw(dest, addrTempRegister, 0); } @@ -601,7 +601,7 @@ public: lw dest, 0(addrTemp) */ DataLabel32 dataLabel(this); - move(Imm32(address.offset), addrTempRegister); + move(TrustedImm32(address.offset), addrTempRegister); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); m_assembler.lw(dest, addrTempRegister, 0); m_fixedWidth = false; @@ -666,7 +666,7 @@ public: sw src, 0(addrTemp) */ DataLabel32 dataLabel(this); - move(Imm32(address.offset), addrTempRegister); + move(TrustedImm32(address.offset), addrTempRegister); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); m_assembler.sw(src, addrTempRegister, 0); m_fixedWidth = false; @@ -719,7 +719,7 @@ public: } } - void store32(Imm32 imm, ImplicitAddress address) + void store32(TrustedImm32 imm, ImplicitAddress address) { if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) { @@ -749,17 +749,17 @@ public: } } - void store32(RegisterID src, void* address) + void store32(RegisterID src, const void* address) { /* li addrTemp, address sw src, 0(addrTemp) */ - move(ImmPtr(address), addrTempRegister); + move(TrustedImmPtr(address), addrTempRegister); m_assembler.sw(src, addrTempRegister, 0); } - void store32(Imm32 imm, void* address) + void store32(TrustedImm32 imm, const void* address) { /* li immTemp, imm @@ -767,11 +767,11 @@ public: sw src, 0(addrTemp) */ if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) { - move(ImmPtr(address), addrTempRegister); + move(TrustedImmPtr(address), addrTempRegister); m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0); } else { move(imm, immTempRegister); - move(ImmPtr(address), addrTempRegister); + move(TrustedImmPtr(address), addrTempRegister); m_assembler.sw(immTempRegister, addrTempRegister, 0); } } @@ -831,7 +831,7 @@ public: push(dataTempRegister); } - void push(Imm32 imm) + void push(TrustedImm32 imm) { move(imm, immTempRegister); push(immTempRegister); @@ -841,7 +841,7 @@ public: // // Move values in registers. - void move(Imm32 imm, RegisterID dest) + void move(TrustedImm32 imm, RegisterID dest) { if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) move(MIPSRegisters::zero, dest); @@ -858,9 +858,9 @@ public: m_assembler.move(dest, src); } - void move(ImmPtr imm, RegisterID dest) + void move(TrustedImmPtr imm, RegisterID dest) { - move(Imm32(imm), dest); + move(TrustedImm32(imm), dest); } void swap(RegisterID reg1, RegisterID reg2) @@ -894,13 +894,13 @@ public: // used (representing the names 'below' and 'above'). // // Operands to the comparision are provided in the expected order, e.g. - // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when + // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when // treated as a signed 32bit value, is less than or equal to 5. // // jz and jnz test whether the first operand is equal to zero, and take // an optional second operand of a mask under which to perform the test. - Jump branch8(Condition cond, Address left, Imm32 right) + Jump branch8(Condition cond, Address left, TrustedImm32 right) { // Make sure the immediate value is unsigned 8 bits. ASSERT(!(right.m_value & 0xFFFFFF00)); @@ -985,7 +985,7 @@ public: return Jump(); } - Jump branch32(Condition cond, RegisterID left, Imm32 right) + Jump branch32(Condition cond, RegisterID left, TrustedImm32 right) { move(right, immTempRegister); return branch32(cond, left, immTempRegister); @@ -1003,14 +1003,14 @@ public: return branch32(cond, dataTempRegister, right); } - Jump branch32(Condition cond, Address left, Imm32 right) + Jump branch32(Condition cond, Address left, TrustedImm32 right) { load32(left, dataTempRegister); move(right, immTempRegister); return branch32(cond, dataTempRegister, immTempRegister); } - Jump branch32(Condition cond, BaseIndex left, Imm32 right) + Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right) { load32(left, dataTempRegister); // Be careful that the previous load32() uses immTempRegister. @@ -1019,7 +1019,7 @@ public: return branch32(cond, dataTempRegister, immTempRegister); } - Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right) + Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right) { load32WithUnalignedHalfWords(left, dataTempRegister); // Be careful that the previous load32WithUnalignedHalfWords() @@ -1035,7 +1035,7 @@ public: return branch32(cond, dataTempRegister, right); } - Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right) + Jump branch32(Condition cond, AbsoluteAddress left, TrustedImm32 right) { load32(left.m_ptr, dataTempRegister); move(right, immTempRegister); @@ -1048,7 +1048,7 @@ public: return branch32(cond, dataTempRegister, right); } - Jump branch16(Condition cond, BaseIndex left, Imm32 right) + Jump branch16(Condition cond, BaseIndex left, TrustedImm32 right) { ASSERT(!(right.m_value & 0xFFFF0000)); load16(left, dataTempRegister); @@ -1067,7 +1067,7 @@ public: return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); } - Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1)) + Jump branchTest32(Condition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) { ASSERT((cond == Zero) || (cond == NonZero)); if (mask.m_value == -1 && !m_fixedWidth) { @@ -1079,19 +1079,19 @@ public: return branchTest32(cond, reg, immTempRegister); } - Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1)) + Jump branchTest32(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { load32(address, dataTempRegister); return branchTest32(cond, dataTempRegister, mask); } - Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1)) + Jump branchTest32(Condition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { load32(address, dataTempRegister); return branchTest32(cond, dataTempRegister, mask); } - Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1)) + Jump branchTest8(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { load8(address, dataTempRegister); return branchTest32(cond, dataTempRegister, mask); @@ -1174,7 +1174,7 @@ public: return Jump(); } - Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest) + Jump branchAdd32(Condition cond, TrustedImm32 imm, RegisterID dest) { move(imm, immTempRegister); return branchAdd32(cond, immTempRegister, dest); @@ -1225,7 +1225,7 @@ public: return Jump(); } - Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest) + Jump branchMul32(Condition cond, TrustedImm32 imm, RegisterID src, RegisterID dest) { move(imm, immTempRegister); move(src, dest); @@ -1279,7 +1279,7 @@ public: return Jump(); } - Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest) + Jump branchSub32(Condition cond, TrustedImm32 imm, RegisterID dest) { move(imm, immTempRegister); return branchSub32(cond, immTempRegister, dest); @@ -1360,7 +1360,7 @@ public: set32Compare32(cond, left, right, dest); } - void set8Compare32(Condition cond, RegisterID left, Imm32 right, RegisterID dest) + void set8Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest) { move(right, immTempRegister); set32Compare32(cond, left, immTempRegister, dest); @@ -1417,13 +1417,13 @@ public: } } - void set32Compare32(Condition cond, RegisterID left, Imm32 right, RegisterID dest) + void set32Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest) { move(right, immTempRegister); set32Compare32(cond, left, immTempRegister, dest); } - void set32Test8(Condition cond, Address address, Imm32 mask, RegisterID dest) + void set32Test8(Condition cond, Address address, TrustedImm32 mask, RegisterID dest) { ASSERT((cond == Zero) || (cond == NonZero)); load8(address, dataTempRegister); @@ -1443,7 +1443,7 @@ public: } } - void set32Test32(Condition cond, Address address, Imm32 mask, RegisterID dest) + void set32Test32(Condition cond, Address address, TrustedImm32 mask, RegisterID dest) { ASSERT((cond == Zero) || (cond == NonZero)); load32(address, dataTempRegister); @@ -1463,7 +1463,7 @@ public: } } - DataLabel32 moveWithPatch(Imm32 imm, RegisterID dest) + DataLabel32 moveWithPatch(TrustedImm32 imm, RegisterID dest) { m_fixedWidth = true; DataLabel32 label(this); @@ -1472,7 +1472,7 @@ public: return label; } - DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest) + DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest) { m_fixedWidth = true; DataLabelPtr label(this); @@ -1481,7 +1481,7 @@ public: return label; } - Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0)) + Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { m_fixedWidth = true; dataLabel = moveWithPatch(initialRightValue, immTempRegister); @@ -1490,7 +1490,7 @@ public: return temp; } - Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0)) + Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { m_fixedWidth = true; load32(left, dataTempRegister); @@ -1500,7 +1500,7 @@ public: return temp; } - DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address) + DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address) { m_fixedWidth = true; DataLabelPtr dataLabel = moveWithPatch(initialValue, dataTempRegister); @@ -1511,14 +1511,14 @@ public: DataLabelPtr storePtrWithPatch(ImplicitAddress address) { - return storePtrWithPatch(ImmPtr(0), address); + return storePtrWithPatch(TrustedImmPtr(0), address); } Call tailRecursiveCall() { // Like a normal call, but don't update the returned address register m_fixedWidth = true; - move(Imm32(0), MIPSRegisters::t9); + move(TrustedImm32(0), MIPSRegisters::t9); m_assembler.jr(MIPSRegisters::t9); m_assembler.nop(); m_fixedWidth = false; @@ -1540,7 +1540,7 @@ public: lwc1 dest, 0(addrTemp) lwc1 dest+1, 4(addrTemp) */ - move(Imm32(address.offset), addrTempRegister); + move(TrustedImm32(address.offset), addrTempRegister); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); m_assembler.lwc1(dest, addrTempRegister, 0); m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4); @@ -1569,7 +1569,7 @@ public: lwc1 dest, 0(addrTemp) lwc1 dest+1, 4(addrTemp) */ - move(ImmPtr(address), addrTempRegister); + move(TrustedImmPtr(address), addrTempRegister); m_assembler.lwc1(dest, addrTempRegister, 0); m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4); #else @@ -1577,7 +1577,7 @@ public: li addrTemp, address ldc1 dest, 0(addrTemp) */ - move(ImmPtr(address), addrTempRegister); + move(TrustedImmPtr(address), addrTempRegister); m_assembler.ldc1(dest, addrTempRegister, 0); #endif } @@ -1592,7 +1592,7 @@ public: swc1 dest, 0(addrTemp) swc1 dest+1, 4(addrTemp) */ - move(Imm32(address.offset), addrTempRegister); + move(TrustedImm32(address.offset), addrTempRegister); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); m_assembler.swc1(src, addrTempRegister, 0); m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4); @@ -1779,7 +1779,7 @@ public: { m_assembler.truncwd(fpTempRegister, src); m_assembler.mfc1(dest, fpTempRegister); - return branch32(Equal, dest, Imm32(0x7fffffff)); + return branch32(Equal, dest, TrustedImm32(0x7fffffff)); } // Convert 'src' to an integer, and places the resulting 'dest'. diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86.h index 92da5f0..b180e2b 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86.h @@ -52,32 +52,32 @@ public: using MacroAssemblerX86Common::loadDouble; using MacroAssemblerX86Common::convertInt32ToDouble; - void add32(Imm32 imm, RegisterID src, RegisterID dest) + void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) { m_assembler.leal_mr(imm.m_value, src, dest); } - void add32(Imm32 imm, AbsoluteAddress address) + void add32(TrustedImm32 imm, AbsoluteAddress address) { m_assembler.addl_im(imm.m_value, address.m_ptr); } - void addWithCarry32(Imm32 imm, AbsoluteAddress address) + void addWithCarry32(TrustedImm32 imm, AbsoluteAddress address) { m_assembler.adcl_im(imm.m_value, address.m_ptr); } - void and32(Imm32 imm, AbsoluteAddress address) + void and32(TrustedImm32 imm, AbsoluteAddress address) { m_assembler.andl_im(imm.m_value, address.m_ptr); } - void or32(Imm32 imm, AbsoluteAddress address) + void or32(TrustedImm32 imm, AbsoluteAddress address) { m_assembler.orl_im(imm.m_value, address.m_ptr); } - void sub32(Imm32 imm, AbsoluteAddress address) + void sub32(TrustedImm32 imm, AbsoluteAddress address) { m_assembler.subl_im(imm.m_value, address.m_ptr); } @@ -98,7 +98,7 @@ public: m_assembler.cvtsi2sd_mr(src.m_ptr, dest); } - void store32(Imm32 imm, void* address) + void store32(TrustedImm32 imm, void* address) { m_assembler.movl_i32m(imm.m_value, address); } @@ -114,7 +114,7 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right) + Jump branch32(Condition cond, AbsoluteAddress left, TrustedImm32 right) { m_assembler.cmpl_im(right.m_value, left.m_ptr); return Jump(m_assembler.jCC(x86Condition(cond))); @@ -136,27 +136,27 @@ public: } - DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest) + DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest) { m_assembler.movl_i32r(initialValue.asIntptr(), dest); return DataLabelPtr(this); } - Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0)) + Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { m_assembler.cmpl_ir_force32(initialRightValue.asIntptr(), left); dataLabel = DataLabelPtr(this); return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0)) + Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { m_assembler.cmpl_im_force32(initialRightValue.asIntptr(), left.offset, left.base); dataLabel = DataLabelPtr(this); return Jump(m_assembler.jCC(x86Condition(cond))); } - DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address) + DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address) { m_assembler.movl_i32m(initialValue.asIntptr(), address.offset, address.base); return DataLabelPtr(this); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h index a02074c..f5829dd 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h @@ -83,7 +83,7 @@ public: // Integer arithmetic operations: // // Operations are typically two operand - operation(source, srcDst) - // For many operations the source may be an Imm32, the srcDst operand + // For many operations the source may be an TrustedImm32, the srcDst operand // may often be a memory location (explictly described using an Address // object). @@ -92,12 +92,12 @@ public: m_assembler.addl_rr(src, dest); } - void add32(Imm32 imm, Address address) + void add32(TrustedImm32 imm, Address address) { m_assembler.addl_im(imm.m_value, address.offset, address.base); } - void add32(Imm32 imm, RegisterID dest) + void add32(TrustedImm32 imm, RegisterID dest) { m_assembler.addl_ir(imm.m_value, dest); } @@ -117,7 +117,7 @@ public: m_assembler.andl_rr(src, dest); } - void and32(Imm32 imm, RegisterID dest) + void and32(TrustedImm32 imm, RegisterID dest) { m_assembler.andl_ir(imm.m_value, dest); } @@ -132,36 +132,64 @@ public: m_assembler.andl_mr(src.offset, src.base, dest); } - void and32(Imm32 imm, Address address) + void and32(TrustedImm32 imm, Address address) { m_assembler.andl_im(imm.m_value, address.offset, address.base); } - void lshift32(Imm32 imm, RegisterID dest) + void and32(RegisterID op1, RegisterID op2, RegisterID dest) { - m_assembler.shll_i8r(imm.m_value, dest); + if (op1 == op2) + zeroExtend32ToPtr(op1, dest); + else if (op1 == dest) + and32(op2, dest); + else { + move(op2, dest); + and32(op1, dest); + } } - + + void and32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + move(src, dest); + and32(imm, dest); + } + void lshift32(RegisterID shift_amount, RegisterID dest) { - // On x86 we can only shift by ecx; if asked to shift by another register we'll - // need rejig the shift amount into ecx first, and restore the registers afterwards. - if (shift_amount != X86Registers::ecx) { - swap(shift_amount, X86Registers::ecx); + ASSERT(shift_amount != dest); - // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx" - if (dest == shift_amount) - m_assembler.shll_CLr(X86Registers::ecx); - // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx" - else if (dest == X86Registers::ecx) - m_assembler.shll_CLr(shift_amount); - // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx" - else - m_assembler.shll_CLr(dest); - - swap(shift_amount, X86Registers::ecx); - } else + if (shift_amount == X86Registers::ecx) m_assembler.shll_CLr(dest); + else { + // On x86 we can only shift by ecx; if asked to shift by another register we'll + // need rejig the shift amount into ecx first, and restore the registers afterwards. + // If we dest is ecx, then shift the swapped register! + swap(shift_amount, X86Registers::ecx); + m_assembler.shll_CLr(dest == X86Registers::ecx ? shift_amount : dest); + swap(shift_amount, X86Registers::ecx); + } + } + + void lshift32(RegisterID src, RegisterID shift_amount, RegisterID dest) + { + ASSERT(shift_amount != dest); + + if (src != dest) + move(src, dest); + lshift32(shift_amount, dest); + } + + void lshift32(TrustedImm32 imm, RegisterID dest) + { + m_assembler.shll_i8r(imm.m_value, dest); + } + + void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + if (src != dest) + move(src, dest); + lshift32(imm, dest); } void mul32(RegisterID src, RegisterID dest) @@ -174,7 +202,7 @@ public: m_assembler.imull_mr(src.offset, src.base, dest); } - void mul32(Imm32 imm, RegisterID src, RegisterID dest) + void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest) { m_assembler.imull_i32r(src, imm.m_value, dest); } @@ -204,7 +232,7 @@ public: m_assembler.orl_rr(src, dest); } - void or32(Imm32 imm, RegisterID dest) + void or32(TrustedImm32 imm, RegisterID dest) { m_assembler.orl_ir(imm.m_value, dest); } @@ -219,76 +247,114 @@ public: m_assembler.orl_mr(src.offset, src.base, dest); } - void or32(Imm32 imm, Address address) + void or32(TrustedImm32 imm, Address address) { m_assembler.orl_im(imm.m_value, address.offset, address.base); } + void or32(RegisterID op1, RegisterID op2, RegisterID dest) + { + if (op1 == op2) + zeroExtend32ToPtr(op1, dest); + else if (op1 == dest) + or32(op2, dest); + else { + move(op2, dest); + or32(op1, dest); + } + } + + void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + move(src, dest); + or32(imm, dest); + } + void rshift32(RegisterID shift_amount, RegisterID dest) { - // On x86 we can only shift by ecx; if asked to shift by another register we'll - // need rejig the shift amount into ecx first, and restore the registers afterwards. - if (shift_amount != X86Registers::ecx) { - swap(shift_amount, X86Registers::ecx); + ASSERT(shift_amount != dest); - // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx" - if (dest == shift_amount) - m_assembler.sarl_CLr(X86Registers::ecx); - // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx" - else if (dest == X86Registers::ecx) - m_assembler.sarl_CLr(shift_amount); - // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx" - else - m_assembler.sarl_CLr(dest); - - swap(shift_amount, X86Registers::ecx); - } else + if (shift_amount == X86Registers::ecx) m_assembler.sarl_CLr(dest); + else { + // On x86 we can only shift by ecx; if asked to shift by another register we'll + // need rejig the shift amount into ecx first, and restore the registers afterwards. + // If we dest is ecx, then shift the swapped register! + swap(shift_amount, X86Registers::ecx); + m_assembler.sarl_CLr(dest == X86Registers::ecx ? shift_amount : dest); + swap(shift_amount, X86Registers::ecx); + } + } + + void rshift32(RegisterID src, RegisterID shift_amount, RegisterID dest) + { + ASSERT(shift_amount != dest); + + if (src != dest) + move(src, dest); + rshift32(shift_amount, dest); } - void rshift32(Imm32 imm, RegisterID dest) + void rshift32(TrustedImm32 imm, RegisterID dest) { m_assembler.sarl_i8r(imm.m_value, dest); } + void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + if (src != dest) + move(src, dest); + rshift32(imm, dest); + } + void urshift32(RegisterID shift_amount, RegisterID dest) { - // On x86 we can only shift by ecx; if asked to shift by another register we'll - // need rejig the shift amount into ecx first, and restore the registers afterwards. - if (shift_amount != X86Registers::ecx) { + ASSERT(shift_amount != dest); + + if (shift_amount == X86Registers::ecx) + m_assembler.shrl_CLr(dest); + else { + // On x86 we can only shift by ecx; if asked to shift by another register we'll + // need rejig the shift amount into ecx first, and restore the registers afterwards. + // If we dest is ecx, then shift the swapped register! swap(shift_amount, X86Registers::ecx); - - // E.g. transform "shrl %eax, %eax" -> "xchgl %eax, %ecx; shrl %ecx, %ecx; xchgl %eax, %ecx" - if (dest == shift_amount) - m_assembler.shrl_CLr(X86Registers::ecx); - // E.g. transform "shrl %eax, %ecx" -> "xchgl %eax, %ecx; shrl %ecx, %eax; xchgl %eax, %ecx" - else if (dest == X86Registers::ecx) - m_assembler.shrl_CLr(shift_amount); - // E.g. transform "shrl %eax, %ebx" -> "xchgl %eax, %ecx; shrl %ecx, %ebx; xchgl %eax, %ecx" - else - m_assembler.shrl_CLr(dest); - + m_assembler.shrl_CLr(dest == X86Registers::ecx ? shift_amount : dest); swap(shift_amount, X86Registers::ecx); - } else - m_assembler.shrl_CLr(dest); + } } - - void urshift32(Imm32 imm, RegisterID dest) + + void urshift32(RegisterID src, RegisterID shift_amount, RegisterID dest) { - m_assembler.shrl_i8r(imm.m_value, dest); + ASSERT(shift_amount != dest); + + if (src != dest) + move(src, dest); + urshift32(shift_amount, dest); } + void urshift32(TrustedImm32 imm, RegisterID dest) + { + m_assembler.shrl_i8r(imm.m_value, dest); + } + + void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + if (src != dest) + move(src, dest); + urshift32(imm, dest); + } + void sub32(RegisterID src, RegisterID dest) { m_assembler.subl_rr(src, dest); } - void sub32(Imm32 imm, RegisterID dest) + void sub32(TrustedImm32 imm, RegisterID dest) { m_assembler.subl_ir(imm.m_value, dest); } - void sub32(Imm32 imm, Address address) + void sub32(TrustedImm32 imm, Address address) { m_assembler.subl_im(imm.m_value, address.offset, address.base); } @@ -309,12 +375,12 @@ public: m_assembler.xorl_rr(src, dest); } - void xor32(Imm32 imm, Address dest) + void xor32(TrustedImm32 imm, Address dest) { m_assembler.xorl_im(imm.m_value, dest.offset, dest.base); } - void xor32(Imm32 imm, RegisterID dest) + void xor32(TrustedImm32 imm, RegisterID dest) { m_assembler.xorl_ir(imm.m_value, dest); } @@ -329,6 +395,24 @@ public: m_assembler.xorl_mr(src.offset, src.base, dest); } + void xor32(RegisterID op1, RegisterID op2, RegisterID dest) + { + if (op1 == op2) + move(TrustedImm32(0), dest); + else if (op1 == dest) + xor32(op2, dest); + else { + move(op2, dest); + xor32(op1, dest); + } + } + + void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + move(src, dest); + xor32(imm, dest); + } + void sqrtDouble(FPRegisterID src, FPRegisterID dst) { m_assembler.sqrtsd_rr(src, dst); @@ -337,7 +421,7 @@ public: // Memory access operations: // // Loads are of the form load(address, destination) and stores of the form - // store(source, address). The source for a store may be an Imm32. Address + // store(source, address). The source for a store may be an TrustedImm32. Address // operand objects to loads and store will be implicitly constructed if a // register is passed. @@ -388,7 +472,7 @@ public: m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale); } - void store32(Imm32 imm, ImplicitAddress address) + void store32(TrustedImm32 imm, ImplicitAddress address) { m_assembler.movl_i32m(imm.m_value, address.offset, address.base); } @@ -398,6 +482,13 @@ public: // // Presently only supports SSE, not x87 floating point. + void moveDouble(FPRegisterID src, FPRegisterID dest) + { + ASSERT(isSSE2Present()); + if (src != dest) + m_assembler.movsd_rr(src, dest); + } + void loadDouble(ImplicitAddress address, FPRegisterID dest) { ASSERT(isSSE2Present()); @@ -416,6 +507,17 @@ public: m_assembler.addsd_rr(src, dest); } + void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + ASSERT(isSSE2Present()); + if (op1 == dest) + addDouble(op2, dest); + else { + moveDouble(op2, dest); + addDouble(op1, dest); + } + } + void addDouble(Address src, FPRegisterID dest) { ASSERT(isSSE2Present()); @@ -428,6 +530,15 @@ public: m_assembler.divsd_rr(src, dest); } + void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + // B := A / B is invalid. + ASSERT(op1 == dest || op2 != dest); + + moveDouble(op1, dest); + divDouble(op2, dest); + } + void divDouble(Address src, FPRegisterID dest) { ASSERT(isSSE2Present()); @@ -440,6 +551,15 @@ public: m_assembler.subsd_rr(src, dest); } + void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + // B := A - B is invalid. + ASSERT(op1 == dest || op2 != dest); + + moveDouble(op1, dest); + subDouble(op2, dest); + } + void subDouble(Address src, FPRegisterID dest) { ASSERT(isSSE2Present()); @@ -452,6 +572,17 @@ public: m_assembler.mulsd_rr(src, dest); } + void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + ASSERT(isSSE2Present()); + if (op1 == dest) + mulDouble(op2, dest); + else { + moveDouble(op2, dest); + mulDouble(op1, dest); + } + } + void mulDouble(Address src, FPRegisterID dest) { ASSERT(isSSE2Present()); @@ -501,11 +632,12 @@ public: // If the result is not representable as a 32 bit value, branch. // May also branch for some values that are representable in 32 bits // (specifically, in this case, INT_MIN). - Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest) + enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful }; + Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed) { ASSERT(isSSE2Present()); m_assembler.cvttsd2si_rr(src, dest); - return branch32(Equal, dest, Imm32(0x80000000)); + return branch32(branchType ? NotEqual : Equal, dest, TrustedImm32(0x80000000)); } // Convert 'src' to an integer, and places the resulting 'dest'. @@ -564,7 +696,7 @@ public: m_assembler.push_m(address.offset, address.base); } - void push(Imm32 imm) + void push(TrustedImm32 imm) { m_assembler.push_i32(imm.m_value); } @@ -574,9 +706,9 @@ public: // // Move values in registers. - void move(Imm32 imm, RegisterID dest) + void move(TrustedImm32 imm, RegisterID dest) { - // Note: on 64-bit the Imm32 value is zero extended into the register, it + // Note: on 64-bit the TrustedImm32 value is zero extended into the register, it // may be useful to have a separate version that sign extends the value? if (!imm.m_value) m_assembler.xorl_rr(dest, dest); @@ -593,7 +725,7 @@ public: m_assembler.movq_rr(src, dest); } - void move(ImmPtr imm, RegisterID dest) + void move(TrustedImmPtr imm, RegisterID dest) { m_assembler.movq_i64r(imm.asIntptr(), dest); } @@ -620,7 +752,7 @@ public: m_assembler.movl_rr(src, dest); } - void move(ImmPtr imm, RegisterID dest) + void move(TrustedImmPtr imm, RegisterID dest) { m_assembler.movl_i32r(imm.asIntptr(), dest); } @@ -655,14 +787,14 @@ public: // used (representing the names 'below' and 'above'). // // Operands to the comparision are provided in the expected order, e.g. - // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when + // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when // treated as a signed 32bit value, is less than or equal to 5. // // jz and jnz test whether the first operand is equal to zero, and take // an optional second operand of a mask under which to perform the test. public: - Jump branch8(Condition cond, Address left, Imm32 right) + Jump branch8(Condition cond, Address left, TrustedImm32 right) { m_assembler.cmpb_im(right.m_value, left.offset, left.base); return Jump(m_assembler.jCC(x86Condition(cond))); @@ -674,7 +806,7 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branch32(Condition cond, RegisterID left, Imm32 right) + Jump branch32(Condition cond, RegisterID left, TrustedImm32 right) { if (((cond == Equal) || (cond == NotEqual)) && !right.m_value) m_assembler.testl_rr(left, left); @@ -695,19 +827,19 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branch32(Condition cond, Address left, Imm32 right) + Jump branch32(Condition cond, Address left, TrustedImm32 right) { m_assembler.cmpl_im(right.m_value, left.offset, left.base); return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branch32(Condition cond, BaseIndex left, Imm32 right) + Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right) { m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale); return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right) + Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right) { return branch32(cond, left, right); } @@ -718,7 +850,7 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branch16(Condition cond, BaseIndex left, Imm32 right) + Jump branch16(Condition cond, BaseIndex left, TrustedImm32 right) { ASSERT(!(right.m_value & 0xFFFF0000)); @@ -728,14 +860,14 @@ public: Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask) { - ASSERT((cond == Zero) || (cond == NonZero)); + ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed)); m_assembler.testl_rr(reg, mask); return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1)) + Jump branchTest32(Condition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) { - ASSERT((cond == Zero) || (cond == NonZero)); + ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed)); // if we are only interested in the low seven bits, this can be tested with a testb if (mask.m_value == -1) m_assembler.testl_rr(reg, reg); @@ -746,9 +878,9 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1)) + Jump branchTest32(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { - ASSERT((cond == Zero) || (cond == NonZero)); + ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed)); if (mask.m_value == -1) m_assembler.cmpl_im(0, address.offset, address.base); else @@ -756,9 +888,9 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1)) + Jump branchTest32(Condition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { - ASSERT((cond == Zero) || (cond == NonZero)); + ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed)); if (mask.m_value == -1) m_assembler.cmpl_im(0, address.offset, address.base, address.index, address.scale); else @@ -766,9 +898,23 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1)) + Jump branchTest8(Condition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) + { + // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values. + ASSERT(mask.m_value >= -128 && mask.m_value <= 255); + ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed)); + if (mask.m_value == -1) + m_assembler.testb_rr(reg, reg); + else + m_assembler.testb_i8r(mask.m_value, reg); + return Jump(m_assembler.jCC(x86Condition(cond))); + } + + Jump branchTest8(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { - ASSERT((cond == Zero) || (cond == NonZero)); + // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values. + ASSERT(mask.m_value >= -128 && mask.m_value <= 255); + ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed)); if (mask.m_value == -1) m_assembler.cmpb_im(0, address.offset, address.base); else @@ -776,9 +922,11 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchTest8(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1)) + Jump branchTest8(Condition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { - ASSERT((cond == Zero) || (cond == NonZero)); + // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values. + ASSERT(mask.m_value >= -128 && mask.m_value <= 255); + ASSERT((cond == Zero) || (cond == NonZero) || (cond == Signed)); if (mask.m_value == -1) m_assembler.cmpb_im(0, address.offset, address.base, address.index, address.scale); else @@ -820,14 +968,14 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest) + Jump branchAdd32(Condition cond, TrustedImm32 imm, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); add32(imm, dest); return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchAdd32(Condition cond, Imm32 src, Address dest) + Jump branchAdd32(Condition cond, TrustedImm32 src, Address dest) { ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero)); add32(src, dest); @@ -848,6 +996,20 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } + Jump branchAdd32(Condition cond, RegisterID src1, RegisterID src2, RegisterID dest) + { + if (src1 == dest) + return branchAdd32(cond, src2, dest); + move(src2, dest); + return branchAdd32(cond, src1, dest); + } + + Jump branchAdd32(Condition cond, TrustedImm32 imm, RegisterID src, RegisterID dest) + { + move(src, dest); + return branchAdd32(cond, imm, dest); + } + Jump branchMul32(Condition cond, RegisterID src, RegisterID dest) { ASSERT(cond == Overflow); @@ -862,13 +1024,21 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest) + Jump branchMul32(Condition cond, TrustedImm32 imm, RegisterID src, RegisterID dest) { ASSERT(cond == Overflow); mul32(imm, src, dest); return Jump(m_assembler.jCC(x86Condition(cond))); } + Jump branchMul32(Condition cond, RegisterID src1, RegisterID src2, RegisterID dest) + { + if (src1 == dest) + return branchMul32(cond, src2, dest); + move(src2, dest); + return branchMul32(cond, src1, dest); + } + Jump branchSub32(Condition cond, RegisterID src, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); @@ -876,14 +1046,14 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest) + Jump branchSub32(Condition cond, TrustedImm32 imm, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); sub32(imm, dest); return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchSub32(Condition cond, Imm32 imm, Address dest) + Jump branchSub32(Condition cond, TrustedImm32 imm, Address dest) { ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero)); sub32(imm, dest); @@ -904,6 +1074,15 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } + Jump branchSub32(Condition cond, RegisterID src1, RegisterID src2, RegisterID dest) + { + // B := A - B is invalid. + ASSERT(src1 == dest || src2 != dest); + + move(src1, dest); + return branchSub32(cond, src2, dest); + } + Jump branchNeg32(Condition cond, RegisterID srcDest) { ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero)); @@ -958,7 +1137,7 @@ public: m_assembler.setCC_r(x86Condition(cond), dest); } - void set8Compare32(Condition cond, RegisterID left, Imm32 right, RegisterID dest) + void set8Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest) { if (((cond == Equal) || (cond == NotEqual)) && !right.m_value) m_assembler.testl_rr(left, left); @@ -974,7 +1153,7 @@ public: m_assembler.movzbl_rr(dest, dest); } - void set32Compare32(Condition cond, RegisterID left, Imm32 right, RegisterID dest) + void set32Compare32(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest) { if (((cond == Equal) || (cond == NotEqual)) && !right.m_value) m_assembler.testl_rr(left, left); @@ -989,7 +1168,7 @@ public: // dest-src, operations always have a dest? ... possibly not true, considering // asm ops like test, or pseudo ops like pop(). - void set32Test8(Condition cond, Address address, Imm32 mask, RegisterID dest) + void set32Test8(Condition cond, Address address, TrustedImm32 mask, RegisterID dest) { if (mask.m_value == -1) m_assembler.cmpb_im(0, address.offset, address.base); @@ -999,7 +1178,7 @@ public: m_assembler.movzbl_rr(dest, dest); } - void set32Test32(Condition cond, Address address, Imm32 mask, RegisterID dest) + void set32Test32(Condition cond, Address address, TrustedImm32 mask, RegisterID dest) { if (mask.m_value == -1) m_assembler.cmpl_im(0, address.offset, address.base); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h index ebbe0bd..bd417aa 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h @@ -48,30 +48,31 @@ public: using MacroAssemblerX86Common::load32; using MacroAssemblerX86Common::store32; using MacroAssemblerX86Common::call; + using MacroAssemblerX86Common::addDouble; using MacroAssemblerX86Common::loadDouble; using MacroAssemblerX86Common::convertInt32ToDouble; - void add32(Imm32 imm, AbsoluteAddress address) + void add32(TrustedImm32 imm, AbsoluteAddress address) { - move(ImmPtr(address.m_ptr), scratchRegister); + move(TrustedImmPtr(address.m_ptr), scratchRegister); add32(imm, Address(scratchRegister)); } - void and32(Imm32 imm, AbsoluteAddress address) + void and32(TrustedImm32 imm, AbsoluteAddress address) { - move(ImmPtr(address.m_ptr), scratchRegister); + move(TrustedImmPtr(address.m_ptr), scratchRegister); and32(imm, Address(scratchRegister)); } - void or32(Imm32 imm, AbsoluteAddress address) + void or32(TrustedImm32 imm, AbsoluteAddress address) { - move(ImmPtr(address.m_ptr), scratchRegister); + move(TrustedImmPtr(address.m_ptr), scratchRegister); or32(imm, Address(scratchRegister)); } - void sub32(Imm32 imm, AbsoluteAddress address) + void sub32(TrustedImm32 imm, AbsoluteAddress address) { - move(ImmPtr(address.m_ptr), scratchRegister); + move(TrustedImmPtr(address.m_ptr), scratchRegister); sub32(imm, Address(scratchRegister)); } @@ -88,17 +89,23 @@ public: void loadDouble(const void* address, FPRegisterID dest) { - move(ImmPtr(address), scratchRegister); + move(TrustedImmPtr(address), scratchRegister); loadDouble(scratchRegister, dest); } - void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest) + void addDouble(AbsoluteAddress address, FPRegisterID dest) { - move(Imm32(*static_cast<int32_t*>(src.m_ptr)), scratchRegister); + move(TrustedImmPtr(address.m_ptr), scratchRegister); + m_assembler.addsd_mr(0, scratchRegister, dest); + } + + void convertInt32ToDouble(TrustedImm32 imm, FPRegisterID dest) + { + move(imm, scratchRegister); m_assembler.cvtsi2sd_rr(scratchRegister, dest); } - void store32(Imm32 imm, void* address) + void store32(TrustedImm32 imm, void* address) { move(X86Registers::eax, scratchRegister); move(imm, X86Registers::eax); @@ -108,7 +115,7 @@ public: Call call() { - DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister); + DataLabelPtr label = moveWithPatch(TrustedImmPtr(0), scratchRegister); Call result = Call(m_assembler.call(scratchRegister), Call::Linkable); ASSERT(differenceBetween(label, result) == REPTACH_OFFSET_CALL_R11); return result; @@ -116,7 +123,7 @@ public: Call tailRecursiveCall() { - DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister); + DataLabelPtr label = moveWithPatch(TrustedImmPtr(0), scratchRegister); Jump newJump = Jump(m_assembler.jmp_r(scratchRegister)); ASSERT(differenceBetween(label, newJump) == REPTACH_OFFSET_CALL_R11); return Call::fromTailJump(newJump); @@ -125,7 +132,7 @@ public: Call makeTailRecursiveCall(Jump oldJump) { oldJump.link(this); - DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister); + DataLabelPtr label = moveWithPatch(TrustedImmPtr(0), scratchRegister); Jump newJump = Jump(m_assembler.jmp_r(scratchRegister)); ASSERT(differenceBetween(label, newJump) == REPTACH_OFFSET_CALL_R11); return Call::fromTailJump(newJump); @@ -137,30 +144,30 @@ public: m_assembler.addq_rr(src, dest); } - void addPtr(Imm32 imm, RegisterID srcDest) + void addPtr(TrustedImm32 imm, RegisterID srcDest) { m_assembler.addq_ir(imm.m_value, srcDest); } - void addPtr(ImmPtr imm, RegisterID dest) + void addPtr(TrustedImmPtr imm, RegisterID dest) { move(imm, scratchRegister); m_assembler.addq_rr(scratchRegister, dest); } - void addPtr(Imm32 imm, RegisterID src, RegisterID dest) + void addPtr(TrustedImm32 imm, RegisterID src, RegisterID dest) { m_assembler.leaq_mr(imm.m_value, src, dest); } - void addPtr(Imm32 imm, Address address) + void addPtr(TrustedImm32 imm, Address address) { m_assembler.addq_im(imm.m_value, address.offset, address.base); } - void addPtr(Imm32 imm, AbsoluteAddress address) + void addPtr(TrustedImm32 imm, AbsoluteAddress address) { - move(ImmPtr(address.m_ptr), scratchRegister); + move(TrustedImmPtr(address.m_ptr), scratchRegister); addPtr(imm, Address(scratchRegister)); } @@ -169,7 +176,7 @@ public: m_assembler.andq_rr(src, dest); } - void andPtr(Imm32 imm, RegisterID srcDest) + void andPtr(TrustedImm32 imm, RegisterID srcDest) { m_assembler.andq_ir(imm.m_value, srcDest); } @@ -179,13 +186,13 @@ public: m_assembler.orq_rr(src, dest); } - void orPtr(ImmPtr imm, RegisterID dest) + void orPtr(TrustedImmPtr imm, RegisterID dest) { move(imm, scratchRegister); m_assembler.orq_rr(scratchRegister, dest); } - void orPtr(Imm32 imm, RegisterID dest) + void orPtr(TrustedImm32 imm, RegisterID dest) { m_assembler.orq_ir(imm.m_value, dest); } @@ -195,12 +202,12 @@ public: m_assembler.subq_rr(src, dest); } - void subPtr(Imm32 imm, RegisterID dest) + void subPtr(TrustedImm32 imm, RegisterID dest) { m_assembler.subq_ir(imm.m_value, dest); } - void subPtr(ImmPtr imm, RegisterID dest) + void subPtr(TrustedImmPtr imm, RegisterID dest) { move(imm, scratchRegister); m_assembler.subq_rr(scratchRegister, dest); @@ -211,7 +218,7 @@ public: m_assembler.xorq_rr(src, dest); } - void xorPtr(Imm32 imm, RegisterID srcDest) + void xorPtr(TrustedImm32 imm, RegisterID srcDest) { m_assembler.xorq_ir(imm.m_value, srcDest); } @@ -227,7 +234,7 @@ public: m_assembler.movq_mr(address.offset, address.base, address.index, address.scale, dest); } - void loadPtr(void* address, RegisterID dest) + void loadPtr(const void* address, RegisterID dest) { if (dest == X86Registers::eax) m_assembler.movq_mEAX(address); @@ -265,7 +272,7 @@ public: } } - void storePtr(ImmPtr imm, ImplicitAddress address) + void storePtr(TrustedImmPtr imm, ImplicitAddress address) { move(imm, scratchRegister); storePtr(scratchRegister, address); @@ -287,7 +294,7 @@ public: m_assembler.movq_rr(src, dest); } - void setPtr(Condition cond, RegisterID left, Imm32 right, RegisterID dest) + void setPtr(Condition cond, RegisterID left, TrustedImm32 right, RegisterID dest) { if (((cond == Equal) || (cond == NotEqual)) && !right.m_value) m_assembler.testq_rr(left, left); @@ -303,7 +310,7 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchPtr(Condition cond, RegisterID left, ImmPtr right) + Jump branchPtr(Condition cond, RegisterID left, TrustedImmPtr right) { move(right, scratchRegister); return branchPtr(cond, left, scratchRegister); @@ -317,7 +324,7 @@ public: Jump branchPtr(Condition cond, AbsoluteAddress left, RegisterID right) { - move(ImmPtr(left.m_ptr), scratchRegister); + move(TrustedImmPtr(left.m_ptr), scratchRegister); return branchPtr(cond, Address(scratchRegister), right); } @@ -327,7 +334,7 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchPtr(Condition cond, Address left, ImmPtr right) + Jump branchPtr(Condition cond, Address left, TrustedImmPtr right) { move(right, scratchRegister); return branchPtr(cond, left, scratchRegister); @@ -339,7 +346,7 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchTestPtr(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1)) + Jump branchTestPtr(Condition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) { // if we are only interested in the low seven bits, this can be tested with a testb if (mask.m_value == -1) @@ -351,7 +358,13 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchTestPtr(Condition cond, Address address, Imm32 mask = Imm32(-1)) + Jump branchTestPtr(Condition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) + { + loadPtr(address.m_ptr, scratchRegister); + return branchTestPtr(cond, scratchRegister, mask); + } + + Jump branchTestPtr(Condition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { if (mask.m_value == -1) m_assembler.cmpq_im(0, address.offset, address.base); @@ -360,7 +373,7 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchTestPtr(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1)) + Jump branchTestPtr(Condition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { if (mask.m_value == -1) m_assembler.cmpq_im(0, address.offset, address.base, address.index, address.scale); @@ -377,32 +390,32 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } - Jump branchSubPtr(Condition cond, Imm32 imm, RegisterID dest) + Jump branchSubPtr(Condition cond, TrustedImm32 imm, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero)); subPtr(imm, dest); return Jump(m_assembler.jCC(x86Condition(cond))); } - DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest) + DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest) { m_assembler.movq_i64r(initialValue.asIntptr(), dest); return DataLabelPtr(this); } - Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0)) + Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { dataLabel = moveWithPatch(initialRightValue, scratchRegister); return branchPtr(cond, left, scratchRegister); } - Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0)) + Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { dataLabel = moveWithPatch(initialRightValue, scratchRegister); return branchPtr(cond, left, scratchRegister); } - DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address) + DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address) { DataLabelPtr label = moveWithPatch(initialValue, scratchRegister); storePtr(scratchRegister, address); @@ -410,9 +423,9 @@ public: } using MacroAssemblerX86Common::branchTest8; - Jump branchTest8(Condition cond, ExtendedAddress address, Imm32 mask = Imm32(-1)) + Jump branchTest8(Condition cond, ExtendedAddress address, TrustedImm32 mask = TrustedImm32(-1)) { - ImmPtr addr(reinterpret_cast<void*>(address.offset)); + TrustedImmPtr addr(reinterpret_cast<void*>(address.offset)); MacroAssemblerX86Common::move(addr, scratchRegister); return MacroAssemblerX86Common::branchTest8(cond, BaseIndex(scratchRegister, address.base, TimesOne), mask); } diff --git a/Source/JavaScriptCore/assembler/X86Assembler.h b/Source/JavaScriptCore/assembler/X86Assembler.h index 587d900..4851c1e 100644 --- a/Source/JavaScriptCore/assembler/X86Assembler.h +++ b/Source/JavaScriptCore/assembler/X86Assembler.h @@ -131,6 +131,7 @@ private: OP_GROUP1_EbIb = 0x80, OP_GROUP1_EvIz = 0x81, OP_GROUP1_EvIb = 0x83, + OP_TEST_EbGb = 0x84, OP_TEST_EvGv = 0x85, OP_XCHG_EvGv = 0x87, OP_MOV_EvGv = 0x89, @@ -228,6 +229,8 @@ public: { } + bool isSet() const { return (m_offset != -1); } + private: JmpSrc(int offset) : m_offset(offset) @@ -299,7 +302,7 @@ public: // Arithmetic operations: #if !CPU(X86_64) - void adcl_im(int imm, void* addr) + void adcl_im(int imm, const void* addr) { if (CAN_SIGN_EXTEND_8_32(imm)) { m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADC, addr); @@ -376,7 +379,7 @@ public: } } #else - void addl_im(int imm, void* addr) + void addl_im(int imm, const void* addr) { if (CAN_SIGN_EXTEND_8_32(imm)) { m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr); @@ -442,7 +445,7 @@ public: } } #else - void andl_im(int imm, void* addr) + void andl_im(int imm, const void* addr) { if (CAN_SIGN_EXTEND_8_32(imm)) { m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, addr); @@ -528,7 +531,7 @@ public: } } #else - void orl_im(int imm, void* addr) + void orl_im(int imm, const void* addr) { if (CAN_SIGN_EXTEND_8_32(imm)) { m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, addr); @@ -594,7 +597,7 @@ public: } } #else - void subl_im(int imm, void* addr) + void subl_im(int imm, const void* addr) { if (CAN_SIGN_EXTEND_8_32(imm)) { m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, addr); @@ -867,12 +870,12 @@ public: } } #else - void cmpl_rm(RegisterID reg, void* addr) + void cmpl_rm(RegisterID reg, const void* addr) { m_formatter.oneByteOp(OP_CMP_EvGv, reg, addr); } - void cmpl_im(int imm, void* addr) + void cmpl_im(int imm, const void* addr) { if (CAN_SIGN_EXTEND_8_32(imm)) { m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, addr); @@ -919,7 +922,12 @@ public: m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset); m_formatter.immediate32(imm); } - + + void testb_rr(RegisterID src, RegisterID dst) + { + m_formatter.oneByteOp(OP_TEST_EbGb, src, dst); + } + void testb_im(int imm, int offset, RegisterID base) { m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, base, offset); @@ -1039,7 +1047,7 @@ public: m_formatter.oneByteOp(OP_MOV_EvGv, src, base, index, scale, offset); } - void movl_mEAX(void* addr) + void movl_mEAX(const void* addr) { m_formatter.oneByteOp(OP_MOV_EAXOv); #if CPU(X86_64) @@ -1076,7 +1084,7 @@ public: m_formatter.immediate32(imm); } - void movl_EAXm(void* addr) + void movl_EAXm(const void* addr) { m_formatter.oneByteOp(OP_MOV_OvEAX); #if CPU(X86_64) @@ -1107,13 +1115,13 @@ public: m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, index, scale, offset); } - void movq_mEAX(void* addr) + void movq_mEAX(const void* addr) { m_formatter.oneByteOp64(OP_MOV_EAXOv); m_formatter.immediate64(reinterpret_cast<int64_t>(addr)); } - void movq_EAXm(void* addr) + void movq_EAXm(const void* addr) { m_formatter.oneByteOp64(OP_MOV_OvEAX); m_formatter.immediate64(reinterpret_cast<int64_t>(addr)); @@ -1153,7 +1161,7 @@ public: #else - void movl_rm(RegisterID src, void* addr) + void movl_rm(RegisterID src, const void* addr) { if (src == X86Registers::eax) movl_EAXm(addr); @@ -1161,7 +1169,7 @@ public: m_formatter.oneByteOp(OP_MOV_EvGv, src, addr); } - void movl_mr(void* addr, RegisterID dst) + void movl_mr(const void* addr, RegisterID dst) { if (dst == X86Registers::eax) movl_mEAX(addr); @@ -1169,7 +1177,7 @@ public: m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr); } - void movl_i32m(int imm, void* addr) + void movl_i32m(int imm, const void* addr) { m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, addr); m_formatter.immediate32(imm); @@ -1365,7 +1373,7 @@ public: } #if !CPU(X86_64) - void cvtsi2sd_mr(void* address, XMMRegisterID dst) + void cvtsi2sd_mr(const void* address, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_F2); m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, address); @@ -1398,6 +1406,12 @@ public: } #endif + void movsd_rr(XMMRegisterID src, XMMRegisterID dst) + { + m_formatter.prefix(PRE_SSE_F2); + m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, (RegisterID)src); + } + void movsd_rm(XMMRegisterID src, int offset, RegisterID base) { m_formatter.prefix(PRE_SSE_F2); @@ -1536,6 +1550,7 @@ public: ASSERT(to.m_offset != -1); char* code = reinterpret_cast<char*>(m_formatter.data()); + ASSERT(!reinterpret_cast<int32_t*>(code + from.m_offset)[-1]); setRel32(code + from.m_offset, code + to.m_offset); } @@ -1717,7 +1732,7 @@ private: } #if !CPU(X86_64) - void oneByteOp(OneByteOpcodeID opcode, int reg, void* address) + void oneByteOp(OneByteOpcodeID opcode, int reg, const void* address) { m_buffer.ensureSpace(maxInstructionSize); m_buffer.putByteUnchecked(opcode); diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index 2d235df..98bbb3c 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -364,7 +364,7 @@ void CodeBlock::dump(ExecState* exec) const unsigned registerIndex = m_numVars; size_t i = 0; do { - printf(" k%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue()).utf8().data()); + printf(" k%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].get()).utf8().data()); ++i; ++registerIndex; } while (i < m_constantRegisters.size()); @@ -731,7 +731,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& case op_resolve_global_dynamic: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; - JSValue scope = JSValue((++it)->u.jsCell); + JSValue scope = JSValue((++it)->u.jsCell.get()); ++it; int depth = (++it)->u.operand; printf("[%4d] resolve_global_dynamic\t %s, %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).utf8().data(), idName(id0, m_identifiers[id0]).data(), depth); @@ -1360,13 +1360,13 @@ void CodeBlock::dumpStatistics() } CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject *globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, SymbolTable* symTab, bool isConstructor) - : m_globalObject(globalObject) + : m_globalObject(globalObject->globalData(), ownerExecutable, globalObject) , m_heap(&m_globalObject->globalData().heap) , m_numCalleeRegisters(0) , m_numVars(0) , m_numParameters(0) , m_isConstructor(isConstructor) - , m_ownerExecutable(ownerExecutable) + , m_ownerExecutable(globalObject->globalData(), ownerExecutable, ownerExecutable) , m_globalData(0) #ifndef NDEBUG , m_instructionCount(0) @@ -1406,12 +1406,6 @@ CodeBlock::~CodeBlock() for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i) m_structureStubInfos[i].deref(); - for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) { - CallLinkInfo* callLinkInfo = &m_callLinkInfos[i]; - if (callLinkInfo->isLinked()) - callLinkInfo->callee->removeCaller(callLinkInfo); - } - for (size_t size = m_methodCallLinkInfos.size(), i = 0; i < size; ++i) { if (Structure* structure = m_methodCallLinkInfos[i].cachedStructure) { structure->deref(); @@ -1421,10 +1415,6 @@ CodeBlock::~CodeBlock() } } -#if ENABLE(JIT_OPTIMIZE_CALL) - unlinkCallers(); -#endif - #endif // ENABLE(JIT) #if DUMP_CODE_BLOCK_STATISTICS @@ -1432,19 +1422,6 @@ CodeBlock::~CodeBlock() #endif } -#if ENABLE(JIT_OPTIMIZE_CALL) -void CodeBlock::unlinkCallers() -{ - size_t size = m_linkedCallerList.size(); - for (size_t i = 0; i < size; ++i) { - CallLinkInfo* currentCaller = m_linkedCallerList[i]; - JIT::unlinkCallOrConstruct(currentCaller); - currentCaller->setUnlinked(); - } - m_linkedCallerList.clear(); -} -#endif - void CodeBlock::derefStructures(Instruction* vPC) const { Interpreter* interpreter = m_globalData->interpreter; @@ -1460,13 +1437,11 @@ void CodeBlock::derefStructures(Instruction* vPC) const } if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) { vPC[4].u.structure->deref(); - vPC[5].u.structureChain->deref(); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) { vPC[4].u.structure->deref(); vPC[5].u.structure->deref(); - vPC[6].u.structureChain->deref(); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) { @@ -1509,13 +1484,11 @@ void CodeBlock::refStructures(Instruction* vPC) const } if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) { vPC[4].u.structure->ref(); - vPC[5].u.structureChain->ref(); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) { vPC[4].u.structure->ref(); vPC[5].u.structure->ref(); - vPC[6].u.structureChain->ref(); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) { @@ -1527,14 +1500,43 @@ void CodeBlock::refStructures(Instruction* vPC) const ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic)); } +void EvalCodeCache::markAggregate(MarkStack& markStack) +{ + EvalCacheMap::iterator end = m_cacheMap.end(); + for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr) + markStack.append(&ptr->second); +} + void CodeBlock::markAggregate(MarkStack& markStack) { - for (size_t i = 0; i < m_constantRegisters.size(); ++i) - markStack.deprecatedAppend(&m_constantRegisters[i]); + markStack.append(&m_globalObject); + markStack.append(&m_ownerExecutable); + if (m_rareData) + m_rareData->m_evalCodeCache.markAggregate(markStack); + markStack.appendValues(m_constantRegisters.data(), m_constantRegisters.size()); for (size_t i = 0; i < m_functionExprs.size(); ++i) - m_functionExprs[i]->markAggregate(markStack); + markStack.append(&m_functionExprs[i]); for (size_t i = 0; i < m_functionDecls.size(); ++i) - m_functionDecls[i]->markAggregate(markStack); + markStack.append(&m_functionDecls[i]); +#if ENABLE(JIT_OPTIMIZE_CALL) + for (unsigned i = 0; i < numberOfCallLinkInfos(); ++i) + if (callLinkInfo(i).isLinked()) + markStack.append(&callLinkInfo(i).callee); +#endif +#if ENABLE(INTERPRETER) + Interpreter* interpreter = m_globalData->interpreter; + for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) { + Instruction* vPC = &m_instructions[m_propertyAccessInstructions[i]]; + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) + markStack.append(&vPC[5].u.structureChain); + else if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) + markStack.append(&vPC[6].u.structureChain); + } +#endif +#if ENABLE(JIT) + for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i) + m_structureStubInfos[i].markAggregate(markStack); +#endif } HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset) @@ -1671,7 +1673,6 @@ void CodeBlock::shrinkToFit() m_structureStubInfos.shrinkToFit(); m_globalResolveInfos.shrinkToFit(); m_callLinkInfos.shrinkToFit(); - m_linkedCallerList.shrinkToFit(); #endif m_identifiers.shrinkToFit(); diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h index bef4561..25e65f4 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.h +++ b/Source/JavaScriptCore/bytecode/CodeBlock.h @@ -96,21 +96,17 @@ namespace JSC { #if ENABLE(JIT) struct CallLinkInfo { CallLinkInfo() - : callee(0) - , position(0) - , hasSeenShouldRepatch(0) + : hasSeenShouldRepatch(false) { } CodeLocationNearCall callReturnLocation; CodeLocationDataLabelPtr hotPathBegin; CodeLocationNearCall hotPathOther; - CodeBlock* ownerCodeBlock; - CodeBlock* callee; - unsigned position : 31; - unsigned hasSeenShouldRepatch : 1; + WriteBarrier<JSFunction> callee; + bool hasSeenShouldRepatch; - void setUnlinked() { callee = 0; } + void setUnlinked() { callee.clear(); } bool isLinked() { return callee; } bool seenOnce() @@ -183,7 +179,7 @@ namespace JSC { unsigned bytecodeOffset; }; - // valueAtPosition helpers for the binaryChop algorithm below. + // valueAtPosition helpers for the binarySearch algorithm. inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo) { @@ -204,42 +200,6 @@ namespace JSC { { return pc->callReturnOffset; } - - // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array, - // compares result with key (KeyTypes should be comparable with '--', '<', '>'). - // Optimized for cases where the array contains the key, checked by assertions. - template<typename ArrayType, typename KeyType, KeyType(*valueAtPosition)(ArrayType*)> - inline ArrayType* binaryChop(ArrayType* array, size_t size, KeyType key) - { - // The array must contain at least one element (pre-condition, array does conatin key). - // If the array only contains one element, no need to do the comparison. - while (size > 1) { - // Pick an element to check, half way through the array, and read the value. - int pos = (size - 1) >> 1; - KeyType val = valueAtPosition(&array[pos]); - - // If the key matches, success! - if (val == key) - return &array[pos]; - // The item we are looking for is smaller than the item being check; reduce the value of 'size', - // chopping off the right hand half of the array. - else if (key < val) - size = pos; - // Discard all values in the left hand half of the array, up to and including the item at pos. - else { - size -= (pos + 1); - array += (pos + 1); - } - - // 'size' should never reach zero. - ASSERT(size); - } - - // If we reach this point we've chopped down to one element, no need to check it matches - ASSERT(size == 1); - ASSERT(key == valueAtPosition(&array[0])); - return &array[0]; - } #endif class CodeBlock { @@ -248,7 +208,7 @@ namespace JSC { protected: CodeBlock(ScriptExecutable* ownerExecutable, CodeType, JSGlobalObject*, PassRefPtr<SourceProvider>, unsigned sourceOffset, SymbolTable* symbolTable, bool isConstructor); - DeprecatedPtr<JSGlobalObject> m_globalObject; + WriteBarrier<JSGlobalObject> m_globalObject; Heap* m_heap; public: @@ -257,9 +217,6 @@ namespace JSC { void markAggregate(MarkStack&); void refStructures(Instruction* vPC) const; void derefStructures(Instruction* vPC) const; -#if ENABLE(JIT_OPTIMIZE_CALL) - void unlinkCallers(); -#endif static void dumpStatistics(); @@ -292,38 +249,20 @@ namespace JSC { void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset); #if ENABLE(JIT) - void addCaller(CallLinkInfo* caller) - { - caller->callee = this; - caller->position = m_linkedCallerList.size(); - m_linkedCallerList.append(caller); - } - - void removeCaller(CallLinkInfo* caller) - { - unsigned pos = caller->position; - unsigned lastPos = m_linkedCallerList.size() - 1; - - if (pos != lastPos) { - m_linkedCallerList[pos] = m_linkedCallerList[lastPos]; - m_linkedCallerList[pos]->position = pos; - } - m_linkedCallerList.shrink(lastPos); - } StructureStubInfo& getStubInfo(ReturnAddressPtr returnAddress) { - return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress.value())); + return *(binarySearch<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress.value())); } CallLinkInfo& getCallLinkInfo(ReturnAddressPtr returnAddress) { - return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress.value())); + return *(binarySearch<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress.value())); } MethodCallLinkInfo& getMethodCallLinkInfo(ReturnAddressPtr returnAddress) { - return *(binaryChop<MethodCallLinkInfo, void*, getMethodCallLinkInfoReturnLocation>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), returnAddress.value())); + return *(binarySearch<MethodCallLinkInfo, void*, getMethodCallLinkInfoReturnLocation>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), returnAddress.value())); } unsigned bytecodeOffset(ReturnAddressPtr returnAddress) @@ -333,7 +272,7 @@ namespace JSC { Vector<CallReturnOffsetToBytecodeOffset>& callIndices = m_rareData->m_callReturnIndexVector; if (!callIndices.size()) return 1; - return binaryChop<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callIndices.begin(), callIndices.size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset; + return binarySearch<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callIndices.begin(), callIndices.size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset; } #endif #if ENABLE(INTERPRETER) @@ -359,7 +298,7 @@ namespace JSC { ExecutablePool* executablePool() { return getJITCode().getExecutablePool(); } #endif - ScriptExecutable* ownerExecutable() const { return m_ownerExecutable; } + ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); } void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; } @@ -451,6 +390,8 @@ namespace JSC { bool hasExpressionInfo() { return m_rareData && m_rareData->m_expressionInfo.size(); } bool hasLineInfo() { return m_rareData && m_rareData->m_lineInfo.size(); } + // We only generate exception handling info if the user is debugging + // (and may want line number info), or if the function contains exception handler. bool needsCallReturnIndices() { return m_rareData && @@ -472,18 +413,34 @@ namespace JSC { Identifier& identifier(int index) { return m_identifiers[index]; } size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); } - void addConstantRegister(const Register& r) { return m_constantRegisters.append(r); } - Register& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; } + void addConstant(JSValue v) + { + m_constantRegisters.append(WriteBarrier<Unknown>()); + m_constantRegisters.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), v); + } + WriteBarrier<Unknown>& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; } ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; } - ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].jsValue(); } + ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); } - unsigned addFunctionDecl(NonNullPassRefPtr<FunctionExecutable> n) { unsigned size = m_functionDecls.size(); m_functionDecls.append(n); return size; } + unsigned addFunctionDecl(FunctionExecutable* n) + { + unsigned size = m_functionDecls.size(); + m_functionDecls.append(WriteBarrier<FunctionExecutable>()); + m_functionDecls.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), n); + return size; + } FunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); } int numberOfFunctionDecls() { return m_functionDecls.size(); } - unsigned addFunctionExpr(NonNullPassRefPtr<FunctionExecutable> n) { unsigned size = m_functionExprs.size(); m_functionExprs.append(n); return size; } + unsigned addFunctionExpr(FunctionExecutable* n) + { + unsigned size = m_functionExprs.size(); + m_functionExprs.append(WriteBarrier<FunctionExecutable>()); + m_functionExprs.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), n); + return size; + } FunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); } - unsigned addRegExp(RegExp* r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; } + unsigned addRegExp(PassRefPtr<RegExp> r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; } RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); } JSGlobalObject* globalObject() { return m_globalObject.get(); } @@ -536,7 +493,7 @@ namespace JSC { m_rareData = adoptPtr(new RareData); } - ScriptExecutable* m_ownerExecutable; + WriteBarrier<ScriptExecutable> m_ownerExecutable; JSGlobalData* m_globalData; Vector<Instruction> m_instructions; @@ -567,16 +524,16 @@ namespace JSC { Vector<GlobalResolveInfo> m_globalResolveInfos; Vector<CallLinkInfo> m_callLinkInfos; Vector<MethodCallLinkInfo> m_methodCallLinkInfos; - Vector<CallLinkInfo*> m_linkedCallerList; #endif Vector<unsigned> m_jumpTargets; // Constant Pool Vector<Identifier> m_identifiers; - Vector<Register> m_constantRegisters; - Vector<RefPtr<FunctionExecutable> > m_functionDecls; - Vector<RefPtr<FunctionExecutable> > m_functionExprs; + COMPILE_ASSERT(sizeof(Register) == sizeof(WriteBarrier<Unknown>), Register_must_be_same_size_as_WriteBarrier_Unknown); + Vector<WriteBarrier<Unknown> > m_constantRegisters; + Vector<WriteBarrier<FunctionExecutable> > m_functionDecls; + Vector<WriteBarrier<FunctionExecutable> > m_functionExprs; SymbolTable* m_symbolTable; @@ -617,12 +574,6 @@ namespace JSC { GlobalCodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset) : CodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, sourceOffset, &m_unsharedSymbolTable, false) { - m_heap->codeBlocks().add(this); - } - - ~GlobalCodeBlock() - { - m_heap->codeBlocks().remove(this); } private: @@ -680,7 +631,7 @@ namespace JSC { { CodeBlock* codeBlock = this->codeBlock(); if (codeBlock->isConstantRegisterIndex(index)) - return codeBlock->constantRegister(index); + return *reinterpret_cast<Register*>(&codeBlock->constantRegister(index)); return this[index]; } diff --git a/Source/JavaScriptCore/bytecode/EvalCodeCache.h b/Source/JavaScriptCore/bytecode/EvalCodeCache.h index edd575f..3e450b1 100644 --- a/Source/JavaScriptCore/bytecode/EvalCodeCache.h +++ b/Source/JavaScriptCore/bytecode/EvalCodeCache.h @@ -41,14 +41,16 @@ namespace JSC { + class MarkStack; + class EvalCodeCache { public: - PassRefPtr<EvalExecutable> get(ExecState* exec, bool inStrictContext, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue) + EvalExecutable* get(ExecState* exec, ScriptExecutable* owner, bool inStrictContext, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue) { - RefPtr<EvalExecutable> evalExecutable; + EvalExecutable* evalExecutable = 0; if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject()) - evalExecutable = m_cacheMap.get(evalSource.impl()); + evalExecutable = m_cacheMap.get(evalSource.impl()).get(); if (!evalExecutable) { evalExecutable = EvalExecutable::create(exec, makeSource(evalSource), inStrictContext); @@ -57,19 +59,21 @@ namespace JSC { return 0; if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries) - m_cacheMap.set(evalSource.impl(), evalExecutable); + m_cacheMap.set(evalSource.impl(), WriteBarrier<EvalExecutable>(exec->globalData(), owner, evalExecutable)); } - return evalExecutable.release(); + return evalExecutable; } bool isEmpty() const { return m_cacheMap.isEmpty(); } + void markAggregate(MarkStack&); + private: static const unsigned maxCacheableSourceLength = 256; static const int maxCacheEntries = 64; - typedef HashMap<RefPtr<StringImpl>, RefPtr<EvalExecutable> > EvalCacheMap; + typedef HashMap<RefPtr<StringImpl>, WriteBarrier<EvalExecutable> > EvalCacheMap; EvalCacheMap m_cacheMap; }; diff --git a/Source/JavaScriptCore/bytecode/Instruction.h b/Source/JavaScriptCore/bytecode/Instruction.h index f077cbf..da0821d 100644 --- a/Source/JavaScriptCore/bytecode/Instruction.h +++ b/Source/JavaScriptCore/bytecode/Instruction.h @@ -63,7 +63,7 @@ namespace JSC { Structure* base; union { Structure* proto; - StructureChain* chain; + WriteBarrierBase<StructureChain> chain; } u; void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base) @@ -82,11 +82,11 @@ namespace JSC { isChain = false; } - void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain) + void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain) { stubRoutine = _stubRoutine; base = _base; - u.chain = _chain; + u.chain.set(globalData, owner, _chain); isChain = true; } } list[POLYMORPHIC_LIST_CACHE_SIZE]; @@ -101,9 +101,9 @@ namespace JSC { list[0].set(stubRoutine, firstBase, firstProto); } - PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain) + PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain) { - list[0].set(stubRoutine, firstBase, firstChain); + list[0].set(globalData, owner, stubRoutine, firstBase, firstChain); } void derefStructures(int count) @@ -115,13 +115,22 @@ namespace JSC { info.base->deref(); if (info.u.proto) { - if (info.isChain) - info.u.chain->deref(); - else + if (!info.isChain) info.u.proto->deref(); } } } + + void markAggregate(MarkStack& markStack, int count) + { + for (int i = 0; i < count; ++i) { + PolymorphicStubInfo& info = list[i]; + ASSERT(info.base); + + if (info.u.proto && info.isChain) + markStack.append(&info.u.chain); + } + } }; struct Instruction { @@ -130,7 +139,7 @@ namespace JSC { #if !ENABLE(COMPUTED_GOTO_INTERPRETER) // We have to initialize one of the pointer members to ensure that // the entire struct is initialized, when opcode is not a pointer. - u.jsCell = 0; + u.jsCell.clear(); #endif u.opcode = opcode; } @@ -139,13 +148,21 @@ namespace JSC { { // We have to initialize one of the pointer members to ensure that // the entire struct is initialized in 64-bit. - u.jsCell = 0; + u.jsCell.clear(); u.operand = operand; } Instruction(Structure* structure) { u.structure = structure; } - Instruction(StructureChain* structureChain) { u.structureChain = structureChain; } - Instruction(JSCell* jsCell) { u.jsCell = jsCell; } + Instruction(JSGlobalData& globalData, JSCell* owner, StructureChain* structureChain) + { + u.structureChain.clear(); + u.structureChain.set(globalData, owner, structureChain); + } + Instruction(JSGlobalData& globalData, JSCell* owner, JSCell* jsCell) + { + u.jsCell.clear(); + u.jsCell.set(globalData, owner, jsCell); + } Instruction(PolymorphicAccessStructureList* polymorphicStructures) { u.polymorphicStructures = polymorphicStructures; } Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; } @@ -153,8 +170,8 @@ namespace JSC { Opcode opcode; int operand; Structure* structure; - StructureChain* structureChain; - JSCell* jsCell; + WriteBarrierBase<StructureChain> structureChain; + WriteBarrierBase<JSCell> jsCell; PolymorphicAccessStructureList* polymorphicStructures; PropertySlot::GetValueFunc getterFunc; } u; diff --git a/Source/JavaScriptCore/bytecode/SamplingTool.h b/Source/JavaScriptCore/bytecode/SamplingTool.h index 9ca54da..a0696b1 100644 --- a/Source/JavaScriptCore/bytecode/SamplingTool.h +++ b/Source/JavaScriptCore/bytecode/SamplingTool.h @@ -95,8 +95,8 @@ namespace JSC { struct Instruction; struct ScriptSampleRecord { - ScriptSampleRecord(ScriptExecutable* executable) - : m_executable(executable) + ScriptSampleRecord(JSGlobalData& globalData, ScriptExecutable* executable) + : m_executable(globalData, executable) , m_codeBlock(0) , m_sampleCount(0) , m_opcodeSampleCount(0) @@ -113,7 +113,7 @@ namespace JSC { void sample(CodeBlock*, Instruction*); - RefPtr<ScriptExecutable> m_executable; + Global<ScriptExecutable> m_executable; CodeBlock* m_codeBlock; int m_sampleCount; int m_opcodeSampleCount; @@ -280,7 +280,6 @@ namespace JSC { // Implements a named set of counters, printed on exit if ENABLE(SAMPLING_COUNTERS). // See subclasses below, SamplingCounter, GlobalSamplingCounter and DeletableSamplingCounter. class AbstractSamplingCounter { - friend class JIT; friend class DeletableSamplingCounter; public: void count(uint32_t count = 1) @@ -290,6 +289,8 @@ namespace JSC { static void dump(); + int64_t* addressOfCounter() { return &m_counter; } + protected: // Effectively the contructor, however called lazily in the case of GlobalSamplingCounter. void init(const char* name) diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp b/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp index 5ec2a3f..4d59ac1 100644 --- a/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp +++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "StructureStubInfo.h" +#include "JSObject.h" #include "ScopeChain.h" namespace JSC { @@ -43,7 +44,6 @@ void StructureStubInfo::deref() return; case access_get_by_id_chain: u.getByIdChain.baseObjectStructure->deref(); - u.getByIdChain.chain->deref(); return; case access_get_by_id_self_list: { PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList; @@ -60,7 +60,6 @@ void StructureStubInfo::deref() case access_put_by_id_transition: u.putByIdTransition.previousStructure->deref(); u.putByIdTransition.structure->deref(); - u.putByIdTransition.chain->deref(); return; case access_put_by_id_replace: u.putByIdReplace.baseObjectStructure->deref(); @@ -77,6 +76,42 @@ void StructureStubInfo::deref() ASSERT_NOT_REACHED(); } } + +void StructureStubInfo::markAggregate(MarkStack& markStack) +{ + switch (accessType) { + case access_get_by_id_self: + return; + case access_get_by_id_proto: + return; + case access_get_by_id_chain: + return; + case access_get_by_id_self_list: { + PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList; + polymorphicStructures->markAggregate(markStack, u.getByIdSelfList.listSize); + return; + } + case access_get_by_id_proto_list: { + PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList; + polymorphicStructures->markAggregate(markStack, u.getByIdProtoList.listSize); + return; + } + case access_put_by_id_transition: + return; + case access_put_by_id_replace: + return; + case access_get_by_id: + case access_put_by_id: + case access_get_by_id_generic: + case access_put_by_id_generic: + case access_get_array_length: + case access_get_string_length: + // These instructions don't ref their Structures. + return; + default: + ASSERT_NOT_REACHED(); + } +} #endif } // namespace JSC diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.h b/Source/JavaScriptCore/bytecode/StructureStubInfo.h index 8e2c489..28202f9 100644 --- a/Source/JavaScriptCore/bytecode/StructureStubInfo.h +++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.h @@ -85,7 +85,6 @@ namespace JSC { baseObjectStructure->ref(); u.getByIdChain.chain = chain; - chain->ref(); } void initGetByIdSelfList(PolymorphicAccessStructureList* structureList, int listSize) @@ -117,7 +116,6 @@ namespace JSC { structure->ref(); u.putByIdTransition.chain = chain; - chain->ref(); } void initPutByIdReplace(Structure* baseObjectStructure) @@ -129,6 +127,7 @@ namespace JSC { } void deref(); + void markAggregate(MarkStack&); bool seenOnce() { diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index 08f4bd4..5af3420 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -224,8 +224,6 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s #endif , m_stack(m_globalData->stack()) , m_usesExceptions(false) - , m_regeneratingForExceptionInfo(false) - , m_codeBlockBeingRegeneratedFrom(0) , m_expressionTooDeep(false) { if (m_shouldEmitDebugHooks) @@ -250,7 +248,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s SymbolTable::iterator end = symbolTable->end(); for (SymbolTable::iterator it = symbolTable->begin(); it != end; ++it) registerFor(it->second.getIndex()).setIndex(it->second.getIndex() + m_globalVarStorageOffset); - + BatchedTransitionOptimizer optimizer(*m_globalData, globalObject); const VarStack& varStack = programNode->varStack(); @@ -260,27 +258,49 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* s // Shift new symbols so they get stored prior to existing symbols. m_nextGlobalIndex -= symbolTable->size(); - size_t oldSymbolTableSize = symbolTable->size(); - + HashSet<StringImpl*, IdentifierRepHash> newGlobals; + Vector<std::pair<int, bool>, 16> functionInfo(functionStack.size()); for (size_t i = 0; i < functionStack.size(); ++i) { FunctionBodyNode* function = functionStack[i]; globalObject->removeDirect(function->ident()); // Make sure our new function is not shadowed by an old property. - emitNewFunction(addGlobalVar(function->ident(), false), function); + SymbolTableEntry entry = symbolTable->inlineGet(function->ident().impl()); + + if (entry.isNull()) + newGlobals.add(function->ident().impl()); + functionInfo[i] = make_pair(entry.getIndex(), entry.isReadOnly()); } - - Vector<RegisterID*, 32> newVars; + + Vector<bool, 16> shouldCreateVar(varStack.size()); for (size_t i = 0; i < varStack.size(); ++i) { - if (globalObject->symbolTableHasProperty(*varStack[i].first) || globalObject->hasProperty(exec, *varStack[i].first)) + if (newGlobals.contains(varStack[i].first->impl()) || globalObject->hasProperty(exec, *varStack[i].first)) { + shouldCreateVar[i] = false; continue; - newVars.append(addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant)); + } + shouldCreateVar[i] = true; + newGlobals.add(varStack[i].first->impl()); } - globalObject->resizeRegisters(oldSymbolTableSize, symbolTable->size()); + int expectedSize = symbolTable->size() + newGlobals.size(); + globalObject->resizeRegisters(symbolTable->size(), expectedSize); + + for (size_t i = 0; i < functionStack.size(); ++i) { + FunctionBodyNode* function = functionStack[i]; + if (functionInfo[i].second) + continue; + RegisterID* dst = addGlobalVar(function->ident(), false); + JSValue value = new (exec) JSFunction(exec, makeFunction(exec, function), scopeChain); + globalObject->registerAt(dst->index() - m_globalVarStorageOffset).set(*m_globalData, globalObject, value); + } - preserveLastVar(); + for (size_t i = 0; i < varStack.size(); ++i) { + if (!shouldCreateVar[i]) + continue; + addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant); + } + if (symbolTable->size() != expectedSize) + CRASH(); - for (size_t i = 0; i < newVars.size(); ++i) - emitLoad(newVars[i], jsUndefined()); + preserveLastVar(); } else { for (size_t i = 0; i < functionStack.size(); ++i) { FunctionBodyNode* function = functionStack[i]; @@ -325,8 +345,6 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainN #endif , m_stack(m_globalData->stack()) , m_usesExceptions(false) - , m_regeneratingForExceptionInfo(false) - , m_codeBlockBeingRegeneratedFrom(0) , m_expressionTooDeep(false) { if (m_shouldEmitDebugHooks) @@ -491,8 +509,6 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeCh #endif , m_stack(m_globalData->stack()) , m_usesExceptions(false) - , m_regeneratingForExceptionInfo(false) - , m_codeBlockBeingRegeneratedFrom(0) , m_expressionTooDeep(false) { if (m_shouldEmitDebugHooks || m_baseScopeDepth) @@ -909,7 +925,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, emitOpcode(op_jneq_ptr); instructions().append(cond->index()); - instructions().append(m_scopeChain->globalObject->d()->callFunction.get()); + instructions().append(Instruction(*m_globalData, m_codeBlock->ownerExecutable(), m_scopeChain->globalObject->callFunction())); instructions().append(target->bind(begin, instructions().size())); return target; } @@ -920,7 +936,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond emitOpcode(op_jneq_ptr); instructions().append(cond->index()); - instructions().append(m_scopeChain->globalObject->d()->applyFunction.get()); + instructions().append(Instruction(*m_globalData, m_codeBlock->ownerExecutable(), m_scopeChain->globalObject->applyFunction())); instructions().append(target->bind(begin, instructions().size())); return target; } @@ -943,14 +959,14 @@ RegisterID* BytecodeGenerator::addConstantValue(JSValue v) if (result.second) { m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset); ++m_nextConstantOffset; - m_codeBlock->addConstantRegister(JSValue(v)); + m_codeBlock->addConstant(JSValue(v)); } else index = result.first->second; return &m_constantPoolRegisters[index]; } -unsigned BytecodeGenerator::addRegExp(RegExp* r) +unsigned BytecodeGenerator::addRegExp(PassRefPtr<RegExp> r) { return m_codeBlock->addRegExp(r); } @@ -1026,8 +1042,8 @@ RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst if (src1->index() == dstIndex && src1->isTemporary() && m_codeBlock->isConstantRegisterIndex(src2->index()) - && m_codeBlock->constantRegister(src2->index()).jsValue().isString()) { - const UString& value = asString(m_codeBlock->constantRegister(src2->index()).jsValue())->tryGetValue(); + && m_codeBlock->constantRegister(src2->index()).get().isString()) { + const UString& value = asString(m_codeBlock->constantRegister(src2->index()).get())->tryGetValue(); if (value == "undefined") { rewindUnaryOp(); emitOpcode(op_is_undefined); @@ -1201,13 +1217,6 @@ RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& pr if (globalObject) { bool forceGlobalResolve = false; - if (m_regeneratingForExceptionInfo) { -#if ENABLE(JIT) - forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInfoAtBytecodeOffset(instructions().size()); -#else - forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInstructionAtBytecodeOffset(instructions().size()); -#endif - } if (index != missingSymbolMarker() && !forceGlobalResolve && !requiresDynamicChecks) { // Directly index the property lookup across multiple scopes. @@ -1344,13 +1353,6 @@ RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, Register } bool forceGlobalResolve = false; - if (m_regeneratingForExceptionInfo) { -#if ENABLE(JIT) - forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInfoAtBytecodeOffset(instructions().size()); -#else - forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInstructionAtBytecodeOffset(instructions().size()); -#endif - } // Global object is the base emitLoad(baseDst, JSValue(globalObject)); @@ -1584,7 +1586,7 @@ RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned return dst; } -RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp) +RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, PassRefPtr<RegExp> regExp) { emitOpcode(op_new_regexp); instructions().append(dst->index()); diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h index b3851c7..3a40390 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -291,7 +291,7 @@ namespace JSC { RegisterID* emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* body); RegisterID* emitNewFunctionInternal(RegisterID* dst, unsigned index, bool shouldNullCheck); RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func); - RegisterID* emitNewRegExp(RegisterID* dst, RegExp* regExp); + RegisterID* emitNewRegExp(RegisterID* dst, PassRefPtr<RegExp> regExp); RegisterID* emitMove(RegisterID* dst, RegisterID* src); @@ -396,12 +396,6 @@ namespace JSC { CodeType codeType() const { return m_codeType; } - void setRegeneratingForExceptionInfo(CodeBlock* originalCodeBlock) - { - m_regeneratingForExceptionInfo = true; - m_codeBlockBeingRegeneratedFrom = originalCodeBlock; - } - bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; } bool isStrictMode() const { return m_codeBlock->isStrictMode(); } @@ -481,14 +475,14 @@ namespace JSC { unsigned addConstant(const Identifier&); RegisterID* addConstantValue(JSValue); - unsigned addRegExp(RegExp*); + unsigned addRegExp(PassRefPtr<RegExp>); - PassRefPtr<FunctionExecutable> makeFunction(ExecState* exec, FunctionBodyNode* body) + FunctionExecutable* makeFunction(ExecState* exec, FunctionBodyNode* body) { return FunctionExecutable::create(exec, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine()); } - PassRefPtr<FunctionExecutable> makeFunction(JSGlobalData* globalData, FunctionBodyNode* body) + FunctionExecutable* makeFunction(JSGlobalData* globalData, FunctionBodyNode* body) { return FunctionExecutable::create(globalData, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine()); } @@ -577,8 +571,6 @@ namespace JSC { StackBounds m_stack; bool m_usesExceptions; - bool m_regeneratingForExceptionInfo; - CodeBlock* m_codeBlockBeingRegeneratedFrom; bool m_expressionTooDeep; }; diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp index 2875434..03578cf 100644 --- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp +++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp @@ -125,9 +125,8 @@ RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d { if (dst == generator.ignoredResult()) return 0; - RefPtr<RegExp> regExp = generator.globalData()->regExpCache()->lookupOrCreate(m_pattern.ustring(), m_flags.ustring()); - ASSERT(regExp->isValid()); - return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get()); + return generator.emitNewRegExp(generator.finalDestination(dst), + generator.globalData()->regExpCache()->lookupOrCreate(m_pattern.ustring(), regExpFlags(m_flags.ustring()))); } // ------------------------------ ThisNode ------------------------------------- diff --git a/Source/JavaScriptCore/collector/handles/Handle.h b/Source/JavaScriptCore/collector/handles/Handle.h index 98c60ec..d4e38c0 100644 --- a/Source/JavaScriptCore/collector/handles/Handle.h +++ b/Source/JavaScriptCore/collector/handles/Handle.h @@ -111,10 +111,19 @@ template <typename Base, typename T> struct HandleConverter { }; template <typename Base> struct HandleConverter<Base, Unknown> { + Handle<JSObject> asObject() const; + bool isObject() const { return jsValue().isObject(); } + bool getNumber(double number) const { return jsValue().getNumber(number); } + UString getString(ExecState*) const; + bool isUndefinedOrNull() const { return jsValue().isUndefinedOrNull(); } + +private: + JSValue jsValue() const { return static_cast<const Base*>(this)->get(); } }; template <typename T> class Handle : public HandleBase, public HandleConverter<Handle<T>, T> { public: + template <typename A, typename B> friend class HandleConverter; typedef typename HandleTypes<T>::ExternalType ExternalType; template <typename U> Handle(Handle<U> o) { @@ -144,6 +153,11 @@ private: } }; +template <typename Base> Handle<JSObject> HandleConverter<Base, Unknown>::asObject() const +{ + return Handle<JSObject>::wrapSlot(static_cast<const Base*>(this)->slot()); +} + template <typename T, typename U> inline bool operator==(const Handle<T>& a, const Handle<U>& b) { return a.get() == b.get(); diff --git a/Source/JavaScriptCore/collector/handles/HandleHeap.cpp b/Source/JavaScriptCore/collector/handles/HandleHeap.cpp index 32fa42d..1beb407 100644 --- a/Source/JavaScriptCore/collector/handles/HandleHeap.cpp +++ b/Source/JavaScriptCore/collector/handles/HandleHeap.cpp @@ -51,11 +51,11 @@ void HandleHeap::grow() } } -void HandleHeap::markStrongHandles(MarkStack& markStack) +void HandleHeap::markStrongHandles(HeapRootMarker& heapRootMarker) { Node* end = m_strongList.end(); for (Node* node = m_strongList.begin(); node != end; node = node->next()) - markStack.deprecatedAppend(node->slot()); + heapRootMarker.mark(node->slot()); } void HandleHeap::updateAfterMark() @@ -79,7 +79,10 @@ void HandleHeap::clearWeakPointers() JSCell* cell = value.asCell(); ASSERT(!cell || cell->structure()); - + +#if ENABLE(JSC_ZOMBIES) + ASSERT(!cell->isZombie()); +#endif if (Heap::isMarked(cell)) continue; diff --git a/Source/JavaScriptCore/collector/handles/HandleHeap.h b/Source/JavaScriptCore/collector/handles/HandleHeap.h index 4bb9b00..ed462d4 100644 --- a/Source/JavaScriptCore/collector/handles/HandleHeap.h +++ b/Source/JavaScriptCore/collector/handles/HandleHeap.h @@ -36,7 +36,7 @@ namespace JSC { class HandleHeap; class JSGlobalData; class JSValue; -class MarkStack; +class HeapRootMarker; class Finalizer { public: @@ -56,7 +56,7 @@ public: void makeWeak(HandleSlot, Finalizer*, void* context); void makeSelfDestroying(HandleSlot, Finalizer*, void* context); - void markStrongHandles(MarkStack&); + void markStrongHandles(HeapRootMarker&); void updateAfterMark(); // Should only be called during teardown. diff --git a/Source/JavaScriptCore/collector/handles/HandleStack.cpp b/Source/JavaScriptCore/collector/handles/HandleStack.cpp new file mode 100644 index 0000000..1c151af --- /dev/null +++ b/Source/JavaScriptCore/collector/handles/HandleStack.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "HandleStack.h" + +#include "MarkStack.h" + +namespace JSC { + +HandleStack::HandleStack() +#ifndef NDEBUG + : m_scopeDepth(0) +#endif +{ + grow(); +} + +void HandleStack::mark(HeapRootMarker& heapRootMarker) +{ + const Vector<HandleSlot>& blocks = m_blockStack.blocks(); + size_t blockLength = m_blockStack.blockLength; + + int end = blocks.size() - 1; + for (int i = 0; i < end; ++i) { + HandleSlot block = blocks[i]; + heapRootMarker.mark(block, blockLength); + } + HandleSlot block = blocks[end]; + heapRootMarker.mark(block, m_frame.m_next - block); +} + +void HandleStack::grow() +{ + HandleSlot block = m_blockStack.grow(); + m_frame.m_next = block; + m_frame.m_end = block + m_blockStack.blockLength; +} + +} diff --git a/Source/JavaScriptCore/collector/handles/HandleStack.h b/Source/JavaScriptCore/collector/handles/HandleStack.h new file mode 100644 index 0000000..54e6c60 --- /dev/null +++ b/Source/JavaScriptCore/collector/handles/HandleStack.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HandleStack_h +#define HandleStack_h + +#include "Assertions.h" +#include "BlockStack.h" +#include "Handle.h" + +#include <wtf/UnusedParam.h> + +namespace JSC { + +class LocalScope; +class HeapRootMarker; + +class HandleStack { +public: + class Frame { + public: + HandleSlot m_next; + HandleSlot m_end; + }; + + HandleStack(); + + void enterScope(Frame&); + void leaveScope(Frame&); + + HandleSlot push(); + + void mark(HeapRootMarker&); + +private: + void grow(); + void zapTo(Frame&); + HandleSlot findFirstAfter(HandleSlot); + +#ifndef NDEBUG + size_t m_scopeDepth; +#endif + BlockStack<JSValue> m_blockStack; + Frame m_frame; +}; + +inline void HandleStack::enterScope(Frame& lastFrame) +{ +#ifndef NDEBUG + ++m_scopeDepth; +#endif + + lastFrame = m_frame; +} + + + +inline void HandleStack::zapTo(Frame& lastFrame) +{ +#ifdef NDEBUG + UNUSED_PARAM(lastFrame); +#else + const Vector<HandleSlot>& blocks = m_blockStack.blocks(); + + if (lastFrame.m_end != m_frame.m_end) { // Zapping to a frame in a different block. + int i = blocks.size() - 1; + for ( ; blocks[i] + m_blockStack.blockLength != lastFrame.m_end; --i) { + for (int j = m_blockStack.blockLength - 1; j >= 0; --j) + blocks[i][j] = JSValue(); + } + + for (HandleSlot it = blocks[i] + m_blockStack.blockLength - 1; it != lastFrame.m_next - 1; --it) + *it = JSValue(); + + return; + } + + for (HandleSlot it = m_frame.m_next - 1; it != lastFrame.m_next - 1; --it) + *it = JSValue(); +#endif +} + +inline void HandleStack::leaveScope(Frame& lastFrame) +{ +#ifndef NDEBUG + --m_scopeDepth; +#endif + + zapTo(lastFrame); + + if (lastFrame.m_end != m_frame.m_end) // Popping to a frame in a different block. + m_blockStack.shrink(lastFrame.m_end); + + m_frame = lastFrame; +} + +inline HandleSlot HandleStack::push() +{ + ASSERT(m_scopeDepth); // Creating a Local outside of a LocalScope is a memory leak. + if (m_frame.m_next == m_frame.m_end) + grow(); + return m_frame.m_next++; +} + +} + +#endif diff --git a/Source/JavaScriptCore/collector/handles/Local.h b/Source/JavaScriptCore/collector/handles/Local.h new file mode 100644 index 0000000..035e9e9 --- /dev/null +++ b/Source/JavaScriptCore/collector/handles/Local.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef Local_h +#define Local_h + +#include "Handle.h" +#include "JSGlobalData.h" + +/* + A Local is a temporary handle whose lifetime is tied to a given LocalScope. + Use Locals for local values on the stack. It is an error to create a Local + outside of any LocalScope. +*/ + +namespace JSC { +template <typename T> class Local; +} + +namespace WTF { + +template<typename T> struct VectorTraits<JSC::Local<T> > { + static const bool needsDestruction = false; + static const bool needsInitialization = true; + static const bool canInitializeWithMemset = false; + static const bool canMoveWithMemcpy = true; + static const bool canCopyWithMemcpy = false; + static const bool canFillWithMemset = false; + static const bool canCompareWithMemcmp = true; +}; + +} + +namespace JSC { + +template <typename T> class Local : public Handle<T> { + friend class LocalScope; +public: + typedef typename Handle<T>::ExternalType ExternalType; + Local(JSGlobalData&, ExternalType = ExternalType()); + Local(JSGlobalData&, Handle<T>); + Local(const Local<T>&); // Adopting constructor. Used to return a Local to a calling function. + + Local& operator=(ExternalType); + Local& operator=(Handle<T>); + + using Handle<T>::slot; + +private: + Local(HandleSlot, ExternalType); // Used by LocalScope::release() to move a Local to a containing scope. + void internalSet(ExternalType value) + { + JSValue newValue(HandleTypes<T>::toJSValue(value)); + HandleSlot slot = this->slot(); + *slot = newValue; + } +}; + +template <typename T> inline Local<T>::Local(JSGlobalData& globalData, ExternalType value) + : Handle<T>(globalData.allocateLocalHandle()) +{ + internalSet(value); +} + +template <typename T> inline Local<T>::Local(JSGlobalData& globalData, Handle<T> handle) + : Handle<T>(globalData.allocateLocalHandle()) +{ + internalSet(handle.get()); +} + +template <typename T> inline Local<T>::Local(const Local<T>& o) + : Handle<T>(o.slot()) +{ + const_cast<Local<T>&>(o).invalidate(); // Prevent accidental sharing. +} + +template <typename T> inline Local<T>::Local(HandleSlot slot, ExternalType value) + : Handle<T>(slot, value) +{ +} + +template <typename T> inline Local<T>& Local<T>::operator=(ExternalType value) +{ + internalSet(value); + return *this; +} + +template <typename T> inline Local<T>& Local<T>::operator=(Handle<T> handle) +{ + internalSet(handle.get()); + return *this; +} + +template <typename T, unsigned inlineCapacity = 0> class LocalStack { + typedef typename Handle<T>::ExternalType ExternalType; +public: + LocalStack(JSGlobalData& globalData) + : m_globalData(&globalData) + , m_count(0) + { + } + + ExternalType peek() const + { + ASSERT(m_count > 0); + return m_stack[m_count - 1].get(); + } + + ExternalType pop() + { + ASSERT(m_count > 0); + return m_stack[--m_count].get(); + } + + void push(ExternalType value) + { + if (m_count == m_stack.size()) + m_stack.append(Local<T>(*m_globalData, value)); + else + m_stack[m_count] = value; + m_count++; + } + + bool isEmpty() const { return !m_count; } + unsigned size() const { return m_count; } + +private: + RefPtr<JSGlobalData> m_globalData; + Vector<Local<T>, inlineCapacity> m_stack; + unsigned m_count; +}; + +} + +#endif diff --git a/Source/JavaScriptCore/collector/handles/LocalScope.h b/Source/JavaScriptCore/collector/handles/LocalScope.h new file mode 100644 index 0000000..cd27b32 --- /dev/null +++ b/Source/JavaScriptCore/collector/handles/LocalScope.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LocalScope_h +#define LocalScope_h + +#include "HandleStack.h" +#include "Local.h" + +namespace JSC { +/* + A LocalScope is a temporary scope in which Locals are allocated. When a + LocalScope goes out of scope, all the Locals created in it are destroyed. + + LocalScope is similar in concept to NSAutoreleasePool. +*/ + +class JSGlobalData; + +class LocalScope { +public: + explicit LocalScope(JSGlobalData&); + ~LocalScope(); + + template <typename T> Local<T> release(Local<T>); // Destroys all other locals in the scope. + +private: + HandleStack* m_handleStack; + HandleStack::Frame m_lastFrame; +}; + +inline LocalScope::LocalScope(JSGlobalData& globalData) + : m_handleStack(globalData.heap.handleStack()) +{ + m_handleStack->enterScope(m_lastFrame); +} + +inline LocalScope::~LocalScope() +{ + m_handleStack->leaveScope(m_lastFrame); +} + +template <typename T> Local<T> LocalScope::release(Local<T> local) +{ + typename Local<T>::ExternalType ptr = local.get(); + + m_handleStack->leaveScope(m_lastFrame); + HandleSlot slot = m_handleStack->push(); + m_handleStack->enterScope(m_lastFrame); + + return Local<T>(slot, ptr); +} + +} + +#endif diff --git a/Source/JavaScriptCore/config.h b/Source/JavaScriptCore/config.h index 1c14917..ea10e77 100644 --- a/Source/JavaScriptCore/config.h +++ b/Source/JavaScriptCore/config.h @@ -29,6 +29,24 @@ #include <wtf/Platform.h> +/* See note in wtf/Platform.h for more info on EXPORT_MACROS. */ +#if USE(EXPORT_MACROS) + +#include <wtf/ExportMacros.h> + +#if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF) +#define WTF_EXPORT_PRIVATE WTF_EXPORT +#define JS_EXPORT_PRIVATE WTF_EXPORT +#else +#define WTF_EXPORT_PRIVATE WTF_IMPORT +#define JS_EXPORT_PRIVATE WTF_IMPORT +#endif + +#define JS_EXPORTDATA JS_EXPORT_PRIVATE +#define JS_EXPORTCLASS JS_EXPORT_PRIVATE + +#else /* !USE(EXPORT_MACROS) */ + #if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !defined(BUILDING_WX__) && !COMPILER(GCC) #if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF) #define JS_EXPORTDATA __declspec(dllexport) @@ -41,6 +59,11 @@ #define JS_EXPORTCLASS #endif +#define WTF_EXPORT_PRIVATE JS_EXPORTDATA +#define JS_EXPORT_PRIVATE JS_EXPORTDATA + +#endif /* USE(EXPORT_MACROS) */ + #if OS(WINDOWS) // If we don't define these, they get defined in windef.h. diff --git a/Source/JavaScriptCore/debugger/Debugger.cpp b/Source/JavaScriptCore/debugger/Debugger.cpp index b999446..64f6002 100644 --- a/Source/JavaScriptCore/debugger/Debugger.cpp +++ b/Source/JavaScriptCore/debugger/Debugger.cpp @@ -29,7 +29,9 @@ #include "Parser.h" #include "Protect.h" -namespace JSC { +namespace { + +using namespace JSC; class Recompiler { public: @@ -82,6 +84,10 @@ inline void Recompiler::operator()(JSCell* cell) m_sourceProviders.add(executable->source().provider(), exec); } +} // namespace + +namespace JSC { + Debugger::~Debugger() { HashSet<JSGlobalObject*>::iterator end = m_globalObjects.end(); @@ -118,16 +124,18 @@ void Debugger::recompileAllJSFunctions(JSGlobalData* globalData) JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject) { CallFrame* globalCallFrame = globalObject->globalExec(); + JSGlobalData& globalData = globalObject->globalData(); - RefPtr<EvalExecutable> eval = EvalExecutable::create(globalCallFrame, makeSource(script), false); - JSObject* error = eval->compile(globalCallFrame, globalCallFrame->scopeChain()); - if (error) - return error; + EvalExecutable* eval = EvalExecutable::create(globalCallFrame, makeSource(script), false); + if (!eval) { + exception = globalData.exception; + globalData.exception = JSValue(); + return exception; + } - JSGlobalData& globalData = globalObject->globalData(); - JSValue result = globalData.interpreter->execute(eval.get(), globalCallFrame, globalObject, globalCallFrame->scopeChain()); + JSValue result = globalData.interpreter->execute(eval, globalCallFrame, globalObject, globalCallFrame->scopeChain()); if (globalData.exception) { - exception = globalData.exception.get(); + exception = globalData.exception; globalData.exception = JSValue(); } ASSERT(result); diff --git a/Source/JavaScriptCore/debugger/DebuggerActivation.cpp b/Source/JavaScriptCore/debugger/DebuggerActivation.cpp index 62a2e54..50ba746 100644 --- a/Source/JavaScriptCore/debugger/DebuggerActivation.cpp +++ b/Source/JavaScriptCore/debugger/DebuggerActivation.cpp @@ -31,7 +31,7 @@ namespace JSC { DebuggerActivation::DebuggerActivation(JSGlobalData& globalData, JSObject* activation) - : JSNonFinalObject(DebuggerActivation::createStructure(jsNull())) + : JSNonFinalObject(DebuggerActivation::createStructure(globalData, jsNull())) { ASSERT(activation); ASSERT(activation->isActivationObject()); diff --git a/Source/JavaScriptCore/debugger/DebuggerActivation.h b/Source/JavaScriptCore/debugger/DebuggerActivation.h index 01a4907..f22d2ff 100644 --- a/Source/JavaScriptCore/debugger/DebuggerActivation.h +++ b/Source/JavaScriptCore/debugger/DebuggerActivation.h @@ -49,9 +49,9 @@ namespace JSC { virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName); virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName); - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: diff --git a/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp b/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp index d778bd5..08fba4a 100644 --- a/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp +++ b/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp @@ -87,16 +87,17 @@ JSValue DebuggerCallFrame::evaluate(const UString& script, JSValue& exception) c { if (!m_callFrame->codeBlock()) return JSValue(); - - RefPtr<EvalExecutable> eval = EvalExecutable::create(m_callFrame, makeSource(script), m_callFrame->codeBlock()->isStrictMode()); - JSObject* error = eval->compile(m_callFrame, m_callFrame->scopeChain()); - if (error) - return error; - + JSGlobalData& globalData = m_callFrame->globalData(); - JSValue result = globalData.interpreter->execute(eval.get(), m_callFrame, thisObject(), m_callFrame->scopeChain()); + EvalExecutable* eval = EvalExecutable::create(m_callFrame, makeSource(script), m_callFrame->codeBlock()->isStrictMode()); + if (globalData.exception) { + exception = globalData.exception; + globalData.exception = JSValue(); + } + + JSValue result = globalData.interpreter->execute(eval, m_callFrame, thisObject(), m_callFrame->scopeChain()); if (globalData.exception) { - exception = globalData.exception.get(); + exception = globalData.exception; globalData.exception = JSValue(); } ASSERT(result); diff --git a/Source/JavaScriptCore/dfg/DFGAliasTracker.h b/Source/JavaScriptCore/dfg/DFGAliasTracker.h new file mode 100644 index 0000000..8710169 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGAliasTracker.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGAliasTracker_h +#define DFGAliasTracker_h + +#if ENABLE(DFG_JIT) + +#include <dfg/DFGGraph.h> +#include <wtf/Vector.h> + +namespace JSC { namespace DFG { + +// === AliasTracker === +// +// This class id used to detect aliasing property accesses, which we may +// be able to speculatively optimize (for example removing redundant loads +// where we know a getter will not be called, or optimizing puts to arrays +// where we know the value being written to in within length and is not a +// hole value). In time, this should be more than a 1-deep buffer! +class AliasTracker { +public: + AliasTracker(Graph& graph) + : m_graph(graph) + , m_candidateAliasGetByVal(NoNode) + { + } + + NodeIndex lookupGetByVal(NodeIndex base, NodeIndex property) + { + // Try to detect situations where a GetByVal follows another GetByVal to the same + // property; in these cases, we may be able to omit the subsequent get on the + // speculative path, where we know conditions hold to make this safe (for example, + // on the speculative path we will not have allowed getter access). + if (m_candidateAliasGetByVal != NoNode) { + Node& possibleAlias = m_graph[m_candidateAliasGetByVal]; + ASSERT(possibleAlias.op == GetByVal); + // This check ensures the accesses alias, provided that the subscript is an + // integer index (this is good enough; the speculative path will only generate + // optimized accesses to handle integer subscripts). + if (possibleAlias.child1 == base && equalIgnoringLaterNumericConversion(possibleAlias.child2, property)) + return m_candidateAliasGetByVal; + } + return NoNode; + } + + void recordGetByVal(NodeIndex getByVal) + { + m_candidateAliasGetByVal = getByVal; + } + + void recordPutByVal(NodeIndex putByVal) + { + ASSERT_UNUSED(putByVal, m_graph[putByVal].op == PutByVal || m_graph[putByVal].op == PutByValAlias); + m_candidateAliasGetByVal = NoNode; + } + + void recordGetById(NodeIndex getById) + { + ASSERT_UNUSED(getById, m_graph[getById].op == GetById); + m_candidateAliasGetByVal = NoNode; + } + + void recordPutById(NodeIndex putById) + { + ASSERT_UNUSED(putById, m_graph[putById].op == PutById); + m_candidateAliasGetByVal = NoNode; + } + + void recordPutByIdDirect(NodeIndex putByVal) + { + ASSERT_UNUSED(putByVal, m_graph[putByVal].op == PutByIdDirect); + m_candidateAliasGetByVal = NoNode; + } + +private: + // This method returns true for arguments: + // - (X, X) + // - (X, ValueToNumber(X)) + // - (X, ValueToInt32(X)) + // - (X, NumberToInt32(X)) + bool equalIgnoringLaterNumericConversion(NodeIndex op1, NodeIndex op2) + { + if (op1 == op2) + return true; + Node& node2 = m_graph[op2]; + return (node2.op == ValueToNumber || node2.op == ValueToInt32 || node2.op == NumberToInt32) && op1 == node2.child1; + } + + // The graph, to look up potentially aliasing nodes. + Graph& m_graph; + // Currently a 1-deep buffer! + NodeIndex m_candidateAliasGetByVal; +}; + +} } // namespace JSC::DFG + +#endif +#endif diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp new file mode 100644 index 0000000..03f5d4f --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp @@ -0,0 +1,744 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DFGByteCodeParser.h" + +#if ENABLE(DFG_JIT) + +#include "DFGAliasTracker.h" +#include "DFGScoreBoard.h" +#include "CodeBlock.h" + +namespace JSC { namespace DFG { + +// === ByteCodeParser === +// +// This class is used to compile the dataflow graph from a CodeBlock. +class ByteCodeParser { +public: + ByteCodeParser(JSGlobalData* globalData, CodeBlock* codeBlock, Graph& graph) + : m_globalData(globalData) + , m_codeBlock(codeBlock) + , m_graph(graph) + , m_currentIndex(0) + , m_noArithmetic(true) + , m_constantUndefined(UINT_MAX) + , m_constant1(UINT_MAX) + { + unsigned numberOfConstants = codeBlock->numberOfConstantRegisters(); + m_constantRecords.grow(numberOfConstants); + + unsigned numberOfParameters = codeBlock->m_numParameters; + m_arguments.grow(numberOfParameters); + for (unsigned i = 0; i < numberOfParameters; ++i) + m_arguments[i] = NoNode; + + unsigned numberOfRegisters = codeBlock->m_numCalleeRegisters; + m_calleeRegisters.grow(numberOfRegisters); + for (unsigned i = 0; i < numberOfRegisters; ++i) + m_calleeRegisters[i] = NoNode; + } + + bool parse(); + +private: + // Get/Set the operands/result of a bytecode instruction. + NodeIndex get(int operand) + { + // Is this a constant? + if (operand >= FirstConstantRegisterIndex) { + unsigned constant = operand - FirstConstantRegisterIndex; + ASSERT(constant < m_constantRecords.size()); + return getJSConstant(constant); + } + + // Is this an argument? + if (operand < 0) { + unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize; + ASSERT(argument < m_arguments.size()); + return getArgument(argument); + } + + // Must be a local or temporary. + ASSERT((unsigned)operand < m_calleeRegisters.size()); + return getRegister((unsigned)operand); + } + void set(int operand, NodeIndex value) + { + // Is this an argument? + if (operand < 0) { + unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize; + ASSERT(argument < m_arguments.size()); + return setArgument(argument, value); + } + + // Must be a local or temporary. + ASSERT((unsigned)operand < m_calleeRegisters.size()); + return setRegister((unsigned)operand, value); + } + + // Used in implementing get/set, above, where the operand is a local or temporary. + NodeIndex getRegister(unsigned operand) + { + NodeIndex index = m_calleeRegisters[operand]; + if (index != NoNode) + return index; + // We have not yet seen a definition for this value in this block. + // For now, since we are only generating single block functions, + // this value must be undefined. + // For example: + // function f() { var x; return x; } + return constantUndefined(); + } + void setRegister(int operand, NodeIndex value) + { + m_calleeRegisters[operand] = value; + } + + // Used in implementing get/set, above, where the operand is an argument. + NodeIndex getArgument(unsigned argument) + { + NodeIndex index = m_arguments[argument]; + if (index != NoNode) + return index; + NodeIndex resultIndex = (NodeIndex)m_graph.size(); + m_graph.append(Node(Argument, m_currentIndex, OpInfo(argument))); + return m_arguments[argument] = resultIndex; + } + void setArgument(int operand, NodeIndex value) + { + m_arguments[operand] = value; + } + + // Get an operand, and perform a ToInt32/ToNumber conversion on it. + NodeIndex getToInt32(int operand) + { + // Avoid wastefully adding a JSConstant node to the graph, only to + // replace it with a Int32Constant (which is what would happen if + // we called 'toInt32(get(operand))' in this case). + if (operand >= FirstConstantRegisterIndex) { + JSValue v = m_codeBlock->getConstant(operand); + if (v.isInt32()) + return getInt32Constant(v.asInt32(), operand - FirstConstantRegisterIndex); + } + return toInt32(get(operand)); + } + NodeIndex getToNumber(int operand) + { + // Avoid wastefully adding a JSConstant node to the graph, only to + // replace it with a DoubleConstant (which is what would happen if + // we called 'toNumber(get(operand))' in this case). + if (operand >= FirstConstantRegisterIndex) { + JSValue v = m_codeBlock->getConstant(operand); + if (v.isNumber()) + return getDoubleConstant(v.uncheckedGetNumber(), operand - FirstConstantRegisterIndex); + } + return toNumber(get(operand)); + } + + // Perform an ES5 ToInt32 operation - returns a node of type NodeResultInt32. + NodeIndex toInt32(NodeIndex index) + { + Node& node = m_graph[index]; + + if (node.hasInt32Result()) + return index; + + if (node.hasDoubleResult()) { + if (node.op == DoubleConstant) + return getInt32Constant(JSC::toInt32(valueOfDoubleConstant(index)), node.constantNumber()); + // 'NumberToInt32(Int32ToNumber(X))' == X, and 'NumberToInt32(UInt32ToNumber(X)) == X' + if (node.op == Int32ToNumber || node.op == UInt32ToNumber) + return node.child1; + + // We unique NumberToInt32 nodes in a map to prevent duplicate conversions. + pair<UnaryOpMap::iterator, bool> result = m_numberToInt32Nodes.add(index, NoNode); + // Either we added a new value, or the existing value in the map is non-zero. + ASSERT(result.second == (result.first->second == NoNode)); + if (result.second) + result.first->second = addToGraph(NumberToInt32, index); + return result.first->second; + } + + // Check for numeric constants boxed as JSValues. + if (node.op == JSConstant) { + JSValue v = valueOfJSConstant(index); + if (v.isInt32()) + return getInt32Constant(v.asInt32(), node.constantNumber()); + if (v.isNumber()) + return getInt32Constant(JSC::toInt32(v.uncheckedGetNumber()), node.constantNumber()); + } + + return addToGraph(ValueToInt32, index); + } + + // Perform an ES5 ToNumber operation - returns a node of type NodeResultDouble. + NodeIndex toNumber(NodeIndex index) + { + Node& node = m_graph[index]; + + if (node.hasDoubleResult()) + return index; + + if (node.hasInt32Result()) { + if (node.op == Int32Constant) + return getDoubleConstant(valueOfInt32Constant(index), node.constantNumber()); + + // We unique Int32ToNumber nodes in a map to prevent duplicate conversions. + pair<UnaryOpMap::iterator, bool> result = m_int32ToNumberNodes.add(index, NoNode); + // Either we added a new value, or the existing value in the map is non-zero. + ASSERT(result.second == (result.first->second == NoNode)); + if (result.second) + result.first->second = addToGraph(Int32ToNumber, index); + return result.first->second; + } + + if (node.op == JSConstant) { + JSValue v = valueOfJSConstant(index); + if (v.isNumber()) + return getDoubleConstant(v.uncheckedGetNumber(), node.constantNumber()); + } + + return addToGraph(ValueToNumber, index); + } + + + // Used in implementing get, above, where the operand is a constant. + NodeIndex getInt32Constant(int32_t value, unsigned constant) + { + NodeIndex index = m_constantRecords[constant].asInt32; + if (index != NoNode) + return index; + NodeIndex resultIndex = (NodeIndex)m_graph.size(); + m_graph.append(Node(Int32Constant, m_currentIndex, OpInfo(constant))); + m_graph[resultIndex].setInt32Constant(value); + m_constantRecords[constant].asInt32 = resultIndex; + return resultIndex; + } + NodeIndex getDoubleConstant(double value, unsigned constant) + { + NodeIndex index = m_constantRecords[constant].asNumeric; + if (index != NoNode) + return index; + NodeIndex resultIndex = (NodeIndex)m_graph.size(); + m_graph.append(Node(DoubleConstant, m_currentIndex, OpInfo(constant))); + m_graph[resultIndex].setDoubleConstant(value); + m_constantRecords[constant].asNumeric = resultIndex; + return resultIndex; + } + NodeIndex getJSConstant(unsigned constant) + { + NodeIndex index = m_constantRecords[constant].asJSValue; + if (index != NoNode) + return index; + + NodeIndex resultIndex = (NodeIndex)m_graph.size(); + m_graph.append(Node(JSConstant, m_currentIndex, OpInfo(constant))); + m_constantRecords[constant].asJSValue = resultIndex; + return resultIndex; + } + + // Helper functions to get/set the this value. + NodeIndex getThis() + { + return getArgument(0); + } + void setThis(NodeIndex value) + { + setArgument(0, value); + } + + // Convenience methods for checking nodes for constants. + bool isInt32Constant(NodeIndex index) + { + return m_graph[index].op == Int32Constant; + } + bool isDoubleConstant(NodeIndex index) + { + return m_graph[index].op == DoubleConstant; + } + bool isJSConstant(NodeIndex index) + { + return m_graph[index].op == JSConstant; + } + + // Convenience methods for getting constant values. + int32_t valueOfInt32Constant(NodeIndex index) + { + ASSERT(isInt32Constant(index)); + return m_graph[index].int32Constant(); + } + double valueOfDoubleConstant(NodeIndex index) + { + ASSERT(isDoubleConstant(index)); + return m_graph[index].numericConstant(); + } + JSValue valueOfJSConstant(NodeIndex index) + { + ASSERT(isJSConstant(index)); + return m_codeBlock->getConstant(FirstConstantRegisterIndex + m_graph[index].constantNumber()); + } + + // This method returns a JSConstant with the value 'undefined'. + NodeIndex constantUndefined() + { + // Has m_constantUndefined been set up yet? + if (m_constantUndefined == UINT_MAX) { + // Search the constant pool for undefined, if we find it, we can just reuse this! + unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters(); + for (m_constantUndefined = 0; m_constantUndefined < numberOfConstants; ++m_constantUndefined) { + JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantUndefined); + if (testMe.isUndefined()) + return getJSConstant(m_constantUndefined); + } + + // Add undefined to the CodeBlock's constants, and add a corresponding slot in m_constantRecords. + ASSERT(m_constantRecords.size() == numberOfConstants); + m_codeBlock->addConstant(jsUndefined()); + m_constantRecords.append(ConstantRecord()); + ASSERT(m_constantRecords.size() == m_codeBlock->numberOfConstantRegisters()); + } + + // m_constantUndefined must refer to an entry in the CodeBlock's constant pool that has the value 'undefined'. + ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantUndefined).isUndefined()); + return getJSConstant(m_constantUndefined); + } + + // This method returns a DoubleConstant with the value 1. + NodeIndex one() + { + // Has m_constant1 been set up yet? + if (m_constant1 == UINT_MAX) { + // Search the constant pool for the value 1, if we find it, we can just reuse this! + unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters(); + for (m_constant1 = 0; m_constant1 < numberOfConstants; ++m_constant1) { + JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1); + if (testMe.isInt32() && testMe.asInt32() == 1) + return getDoubleConstant(1, m_constant1); + } + + // Add the value 1 to the CodeBlock's constants, and add a corresponding slot in m_constantRecords. + ASSERT(m_constantRecords.size() == numberOfConstants); + m_codeBlock->addConstant(jsNumber(1)); + m_constantRecords.append(ConstantRecord()); + ASSERT(m_constantRecords.size() == m_codeBlock->numberOfConstantRegisters()); + } + + // m_constant1 must refer to an entry in the CodeBlock's constant pool that has the integer value 1. + ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).isInt32()); + ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).asInt32() == 1); + return getDoubleConstant(1, m_constant1); + } + + + // These methods create a node and add it to the graph. If nodes of this type are + // 'mustGenerate' then the node will implicitly be ref'ed to ensure generation. + NodeIndex addToGraph(NodeType op, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) + { + NodeIndex resultIndex = (NodeIndex)m_graph.size(); + m_graph.append(Node(op, m_currentIndex, child1, child2, child3)); + + if (op & NodeMustGenerate) + m_graph.ref(resultIndex); + return resultIndex; + } + NodeIndex addToGraph(NodeType op, OpInfo info, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) + { + NodeIndex resultIndex = (NodeIndex)m_graph.size(); + m_graph.append(Node(op, m_currentIndex, info, child1, child2, child3)); + + if (op & NodeMustGenerate) + m_graph.ref(resultIndex); + return resultIndex; + } + + JSGlobalData* m_globalData; + CodeBlock* m_codeBlock; + Graph& m_graph; + + // The bytecode index of the current instruction being generated. + unsigned m_currentIndex; + + // FIXME: used to temporarily disable arithmetic, until we fix associated performance regressions. + bool m_noArithmetic; + + // We use these values during code generation, and to avoid the need for + // special handling we make sure they are available as constants in the + // CodeBlock's constant pool. These variables are initialized to + // UINT_MAX, and lazily updated to hold an index into the CodeBlock's + // constant pool, as necessary. + unsigned m_constantUndefined; + unsigned m_constant1; + + // A constant in the constant pool may be represented by more than one + // node in the graph, depending on the context in which it is being used. + struct ConstantRecord { + ConstantRecord() + : asInt32(NoNode) + , asNumeric(NoNode) + , asJSValue(NoNode) + { + } + + NodeIndex asInt32; + NodeIndex asNumeric; + NodeIndex asJSValue; + }; + Vector <ConstantRecord, 32> m_constantRecords; + + // Track the index of the node whose result is the current value for every + // register value in the bytecode - argument, local, and temporary. + Vector <NodeIndex, 32> m_arguments; + Vector <NodeIndex, 32> m_calleeRegisters; + + // These maps are used to unique ToNumber and ToInt32 operations. + typedef HashMap<NodeIndex, NodeIndex> UnaryOpMap; + UnaryOpMap m_int32ToNumberNodes; + UnaryOpMap m_numberToInt32Nodes; +}; + +#define NEXT_OPCODE(name) \ + m_currentIndex += OPCODE_LENGTH(name); \ + continue; + +bool ByteCodeParser::parse() +{ + AliasTracker aliases(m_graph); + + Interpreter* interpreter = m_globalData->interpreter; + Instruction* instructionsBegin = m_codeBlock->instructions().begin(); + while (true) { + // Switch on the current bytecode opcode. + Instruction* currentInstruction = instructionsBegin + m_currentIndex; + switch (interpreter->getOpcodeID(currentInstruction->u.opcode)) { + + // === Function entry opcodes === + + case op_enter: + // This is a no-op for now - may need to initialize locals, if + // DCE analysis cannot determine that the values are never read. + NEXT_OPCODE(op_enter); + + case op_convert_this: { + NodeIndex op1 = getThis(); + setThis(addToGraph(ConvertThis, op1)); + NEXT_OPCODE(op_convert_this); + } + + // === Bitwise operations === + + case op_bitand: { + NodeIndex op1 = getToInt32(currentInstruction[2].u.operand); + NodeIndex op2 = getToInt32(currentInstruction[3].u.operand); + set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2)); + NEXT_OPCODE(op_bitand); + } + + case op_bitor: { + NodeIndex op1 = getToInt32(currentInstruction[2].u.operand); + NodeIndex op2 = getToInt32(currentInstruction[3].u.operand); + set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2)); + NEXT_OPCODE(op_bitor); + } + + case op_bitxor: { + NodeIndex op1 = getToInt32(currentInstruction[2].u.operand); + NodeIndex op2 = getToInt32(currentInstruction[3].u.operand); + set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2)); + NEXT_OPCODE(op_bitxor); + } + + case op_rshift: { + NodeIndex op1 = getToInt32(currentInstruction[2].u.operand); + NodeIndex op2 = getToInt32(currentInstruction[3].u.operand); + NodeIndex result; + // Optimize out shifts by zero. + if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f)) + result = op1; + else + result = addToGraph(BitRShift, op1, op2); + set(currentInstruction[1].u.operand, result); + NEXT_OPCODE(op_rshift); + } + + case op_lshift: { + NodeIndex op1 = getToInt32(currentInstruction[2].u.operand); + NodeIndex op2 = getToInt32(currentInstruction[3].u.operand); + NodeIndex result; + // Optimize out shifts by zero. + if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f)) + result = op1; + else + result = addToGraph(BitLShift, op1, op2); + set(currentInstruction[1].u.operand, result); + NEXT_OPCODE(op_lshift); + } + + case op_urshift: { + NodeIndex op1 = getToInt32(currentInstruction[2].u.operand); + NodeIndex op2 = getToInt32(currentInstruction[3].u.operand); + NodeIndex result; + // The result of a zero-extending right shift is treated as an unsigned value. + // This means that if the top bit is set, the result is not in the int32 range, + // and as such must be stored as a double. If the shift amount is a constant, + // we may be able to optimize. + if (isInt32Constant(op2)) { + // If we know we are shifting by a non-zero amount, then since the operation + // zero fills we know the top bit of the result must be zero, and as such the + // result must be within the int32 range. Conversely, if this is a shift by + // zero, then the result may be changed by the conversion to unsigned, but it + // is not necessary to perform the shift! + if (valueOfInt32Constant(op2) & 0x1f) + result = addToGraph(BitURShift, op1, op2); + else + result = addToGraph(UInt32ToNumber, op1); + } else { + // Cannot optimize at this stage; shift & potentially rebox as a double. + result = addToGraph(BitURShift, op1, op2); + result = addToGraph(UInt32ToNumber, result); + } + set(currentInstruction[1].u.operand, result); + NEXT_OPCODE(op_urshift); + } + + // === Increment/Decrement opcodes === + + case op_pre_inc: { + unsigned srcDst = currentInstruction[1].u.operand; + NodeIndex op = getToNumber(srcDst); + set(srcDst, addToGraph(ArithAdd, op, one())); + NEXT_OPCODE(op_pre_inc); + } + + case op_post_inc: { + unsigned result = currentInstruction[1].u.operand; + unsigned srcDst = currentInstruction[2].u.operand; + NodeIndex op = getToNumber(srcDst); + set(result, op); + set(srcDst, addToGraph(ArithAdd, op, one())); + NEXT_OPCODE(op_post_inc); + } + + case op_pre_dec: { + unsigned srcDst = currentInstruction[1].u.operand; + NodeIndex op = getToNumber(srcDst); + set(srcDst, addToGraph(ArithSub, op, one())); + NEXT_OPCODE(op_pre_dec); + } + + case op_post_dec: { + unsigned result = currentInstruction[1].u.operand; + unsigned srcDst = currentInstruction[2].u.operand; + NodeIndex op = getToNumber(srcDst); + set(result, op); + set(srcDst, addToGraph(ArithSub, op, one())); + NEXT_OPCODE(op_post_dec); + } + + // === Arithmetic operations === + + case op_add: { + m_noArithmetic = false; + NodeIndex op1 = get(currentInstruction[2].u.operand); + NodeIndex op2 = get(currentInstruction[3].u.operand); + // If both operands can statically be determined to the numbers, then this is an arithmetic add. + // Otherwise, we must assume this may be performing a concatenation to a string. + if (m_graph[op1].hasNumericResult() && m_graph[op2].hasNumericResult()) + set(currentInstruction[1].u.operand, addToGraph(ArithAdd, toNumber(op1), toNumber(op2))); + else + set(currentInstruction[1].u.operand, addToGraph(ValueAdd, op1, op2)); + NEXT_OPCODE(op_add); + } + + case op_sub: { + m_noArithmetic = false; + NodeIndex op1 = getToNumber(currentInstruction[2].u.operand); + NodeIndex op2 = getToNumber(currentInstruction[3].u.operand); + set(currentInstruction[1].u.operand, addToGraph(ArithSub, op1, op2)); + NEXT_OPCODE(op_sub); + } + + case op_mul: { + m_noArithmetic = false; + NodeIndex op1 = getToNumber(currentInstruction[2].u.operand); + NodeIndex op2 = getToNumber(currentInstruction[3].u.operand); + set(currentInstruction[1].u.operand, addToGraph(ArithMul, op1, op2)); + NEXT_OPCODE(op_mul); + } + + case op_mod: { + m_noArithmetic = false; + NodeIndex op1 = getToNumber(currentInstruction[2].u.operand); + NodeIndex op2 = getToNumber(currentInstruction[3].u.operand); + set(currentInstruction[1].u.operand, addToGraph(ArithMod, op1, op2)); + NEXT_OPCODE(op_mod); + } + + case op_div: { + m_noArithmetic = false; + NodeIndex op1 = getToNumber(currentInstruction[2].u.operand); + NodeIndex op2 = getToNumber(currentInstruction[3].u.operand); + set(currentInstruction[1].u.operand, addToGraph(ArithDiv, op1, op2)); + NEXT_OPCODE(op_div); + } + + // === Misc operations === + + case op_mov: { + NodeIndex op = get(currentInstruction[2].u.operand); + set(currentInstruction[1].u.operand, op); + NEXT_OPCODE(op_mov); + } + + // === Property access operations === + + case op_get_by_val: { + NodeIndex base = get(currentInstruction[2].u.operand); + NodeIndex property = get(currentInstruction[3].u.operand); + + NodeIndex getByVal = addToGraph(GetByVal, base, property, aliases.lookupGetByVal(base, property)); + set(currentInstruction[1].u.operand, getByVal); + aliases.recordGetByVal(getByVal); + + NEXT_OPCODE(op_get_by_val); + }; + + case op_put_by_val: { + NodeIndex base = get(currentInstruction[1].u.operand); + NodeIndex property = get(currentInstruction[2].u.operand); + NodeIndex value = get(currentInstruction[3].u.operand); + + NodeIndex aliasedGet = aliases.lookupGetByVal(base, property); + NodeIndex putByVal = addToGraph(aliasedGet != NoNode ? PutByValAlias : PutByVal, base, property, value); + aliases.recordPutByVal(putByVal); + + NEXT_OPCODE(op_put_by_val); + }; + + case op_get_by_id: { + NodeIndex base = get(currentInstruction[2].u.operand); + unsigned identifier = currentInstruction[3].u.operand; + + NodeIndex getById = addToGraph(GetById, OpInfo(identifier), base); + set(currentInstruction[1].u.operand, getById); + aliases.recordGetById(getById); + + NEXT_OPCODE(op_get_by_id); + } + + case op_put_by_id: { + NodeIndex value = get(currentInstruction[3].u.operand); + NodeIndex base = get(currentInstruction[1].u.operand); + unsigned identifier = currentInstruction[2].u.operand; + bool direct = currentInstruction[8].u.operand; + + if (direct) { + NodeIndex putByIdDirect = addToGraph(PutByIdDirect, OpInfo(identifier), base, value); + aliases.recordPutByIdDirect(putByIdDirect); + } else { + NodeIndex putById = addToGraph(PutById, OpInfo(identifier), base, value); + aliases.recordPutById(putById); + } + + NEXT_OPCODE(op_put_by_id); + } + + case op_get_global_var: { + NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand)); + set(currentInstruction[1].u.operand, getGlobalVar); + NEXT_OPCODE(op_get_global_var); + } + + case op_put_global_var: { + NodeIndex value = get(currentInstruction[2].u.operand); + addToGraph(PutGlobalVar, OpInfo(currentInstruction[1].u.operand), value); + NEXT_OPCODE(op_put_global_var); + } + + // === Block terminators. === + + case op_ret: { + addToGraph(Return, get(currentInstruction[1].u.operand)); + m_currentIndex += OPCODE_LENGTH(op_ret); +#if ENABLE(DFG_JIT_RESTRICTIONS) + // FIXME: temporarily disabling the DFG JIT for functions containing arithmetic. + return m_noArithmetic; +#else + return true; +#endif + } + + default: + // parse failed! + return false; + } + } +} + +bool parse(Graph& graph, JSGlobalData* globalData, CodeBlock* codeBlock) +{ + // Call ByteCodeParser::parse to build the dataflow for the basic block at 'startIndex'. + ByteCodeParser state(globalData, codeBlock, graph); + if (!state.parse()) + return false; + + // Assign VirtualRegisters. + ScoreBoard scoreBoard(graph); + Node* nodes = graph.begin(); + size_t size = graph.size(); + for (size_t i = 0; i < size; ++i) { + Node& node = nodes[i]; + if (node.refCount) { + // First, call use on all of the current node's children, then + // allocate a VirtualRegister for this node. We do so in this + // order so that if a child is on its last use, and a + // VirtualRegister is freed, then it may be reused for node. + scoreBoard.use(node.child1); + scoreBoard.use(node.child2); + scoreBoard.use(node.child3); + node.virtualRegister = scoreBoard.allocate(); + // 'mustGenerate' nodes have their useCount artificially elevated, + // call use now to account for this. + if (node.mustGenerate()) + scoreBoard.use(i); + } + } + + // 'm_numCalleeRegisters' is the number of locals and temporaries allocated + // for the function (and checked for on entry). Since we perform a new and + // different allocation of temporaries, more registers may now be required. + if ((unsigned)codeBlock->m_numCalleeRegisters < scoreBoard.allocatedCount()) + codeBlock->m_numCalleeRegisters = scoreBoard.allocatedCount(); + +#if DFG_DEBUG_VERBOSE + graph.dump(codeBlock); +#endif + return true; +} + +} } // namespace JSC::DFG + +#endif diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.h b/Source/JavaScriptCore/dfg/DFGByteCodeParser.h new file mode 100644 index 0000000..d4efe61 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGByteCodeParser_h +#define DFGByteCodeParser_h + +#if ENABLE(DFG_JIT) + +#include <dfg/DFGGraph.h> + +namespace JSC { + +class CodeBlock; +class JSGlobalData; + +namespace DFG { + +// Populate the Graph with a basic block of code from the CodeBlock, +// starting at the provided bytecode index. +bool parse(Graph&, JSGlobalData*, CodeBlock*); + +} } // namespace JSC::DFG + +#endif +#endif diff --git a/Source/JavaScriptCore/dfg/DFGGenerationInfo.h b/Source/JavaScriptCore/dfg/DFGGenerationInfo.h new file mode 100644 index 0000000..b3aa0cd --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGGenerationInfo.h @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGGenerationInfo_h +#define DFGGenerationInfo_h + +#if ENABLE(DFG_JIT) + +#include <dfg/DFGJITCompiler.h> + +namespace JSC { namespace DFG { + +// === DataFormat === +// +// This enum tracks the current representation in which a value is being held. +// Values may be unboxed primitives (int32, double, or cell), or boxed as a JSValue. +// For boxed values, we may know the type of boxing that has taken place. +// (May also need bool, array, object, string types!) +enum DataFormat { + DataFormatNone = 0, + DataFormatInteger = 1, + DataFormatDouble = 2, + DataFormatCell = 3, + DataFormatJS = 8, + DataFormatJSInteger = DataFormatJS | DataFormatInteger, + DataFormatJSDouble = DataFormatJS | DataFormatDouble, + DataFormatJSCell = DataFormatJS | DataFormatCell, +}; + +// === GenerationInfo === +// +// This class is used to track the current status of a live values during code generation. +// Can provide information as to whether a value is in machine registers, and if so which, +// whether a value has been spilled to the RegsiterFile, and if so may be able to provide +// details of the format in memory (all values are spilled in a boxed form, but we may be +// able to track the type of box), and tracks how many outstanding uses of a value remain, +// so that we know when the value is dead and the machine registers associated with it +// may be released. +class GenerationInfo { +public: + GenerationInfo() + : m_nodeIndex(NoNode) + , m_useCount(0) + , m_registerFormat(DataFormatNone) + , m_spillFormat(DataFormatNone) + , m_canFill(false) + { + } + + // Used to set the generation info according the the result + // of various operations. + void initArgument(NodeIndex nodeIndex, uint32_t useCount) + { + m_nodeIndex = nodeIndex; + m_useCount = useCount; + m_registerFormat = DataFormatNone; + m_spillFormat = DataFormatNone; + m_canFill = true; + } + void initConstant(NodeIndex nodeIndex, uint32_t useCount) + { + m_nodeIndex = nodeIndex; + m_useCount = useCount; + m_registerFormat = DataFormatNone; + m_spillFormat = DataFormatNone; + m_canFill = true; + } + void initInteger(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr) + { + m_nodeIndex = nodeIndex; + m_useCount = useCount; + m_registerFormat = DataFormatInteger; + m_spillFormat = DataFormatNone; + m_canFill = false; + u.gpr = gpr; + } + void initJSValue(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr, DataFormat format = DataFormatJS) + { + ASSERT(format & DataFormatJS); + + m_nodeIndex = nodeIndex; + m_useCount = useCount; + m_registerFormat = format; + m_spillFormat = DataFormatNone; + m_canFill = false; + u.gpr = gpr; + } + void initCell(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr) + { + m_nodeIndex = nodeIndex; + m_useCount = useCount; + m_registerFormat = DataFormatCell; + m_spillFormat = DataFormatNone; + m_canFill = false; + u.gpr = gpr; + } + void initDouble(NodeIndex nodeIndex, uint32_t useCount, FPRReg fpr) + { + m_nodeIndex = nodeIndex; + m_useCount = useCount; + m_registerFormat = DataFormatDouble; + m_spillFormat = DataFormatNone; + m_canFill = false; + u.fpr = fpr; + } + void initNone(NodeIndex nodeIndex, uint32_t useCount) + { + m_nodeIndex = nodeIndex; + m_useCount = useCount; + m_registerFormat = DataFormatNone; + m_spillFormat = DataFormatNone; + m_canFill = false; + } + + // Get the index of the node that produced this value. + NodeIndex nodeIndex() { return m_nodeIndex; } + + // Mark the value as having been used (decrement the useCount). + // Returns true if this was the last use of the value, and any + // associated machine registers may be freed. + bool use() + { + return !--m_useCount; + } + + // Used to check the operands of operations to see if they are on + // their last use; in some cases it may be safe to reuse the same + // machine register for the result of the operation. + bool canReuse() + { + ASSERT(m_useCount); + return m_useCount == 1; + } + + // Get the format of the value in machine registers (or 'none'). + DataFormat registerFormat() { return m_registerFormat; } + // Get the format of the value as it is spilled in the RegisterFile (or 'none'). + DataFormat spillFormat() { return m_spillFormat; } + + // Get the machine resister currently holding the value. + GPRReg gpr() { ASSERT(m_registerFormat && m_registerFormat != DataFormatDouble); return u.gpr; } + FPRReg fpr() { ASSERT(m_registerFormat == DataFormatDouble); return u.fpr; } + + // Check whether a value needs spilling in order to free up any associated machine registers. + bool needsSpill() + { + // This should only be called on values that are currently in a register. + ASSERT(m_registerFormat != DataFormatNone); + // Constants and arguments do not need spilling, nor do values + // that have already been spilled to the RegisterFile. + return !m_canFill; + } + + // Called when a VirtualRegister is being spilled †o the RegisterFile for the first time. + void spill(DataFormat spillFormat) + { + // We shouldn't be spill values that don't need spilling. + ASSERT(!m_canFill); + ASSERT(m_spillFormat == DataFormatNone); + // We should only be spilling values that are currently in machine registers. + ASSERT(m_registerFormat != DataFormatNone); + // We only spill values that have been boxed as a JSValue; otherwise the GC + // would need a way to distinguish cell pointers from numeric primitives. + ASSERT(spillFormat & DataFormatJS); + + m_registerFormat = DataFormatNone; + m_spillFormat = spillFormat; + m_canFill = true; + } + + // Called on values that don't need spilling (constants, arguments, + // values that have already been spilled), to mark them as no longer + // being in machine registers. + void setSpilled() + { + // Should only be called on values that don't need spilling, and are currently in registers. + ASSERT(m_canFill && m_registerFormat != DataFormatNone); + m_registerFormat = DataFormatNone; + } + + // Record that this value is filled into machine registers, + // tracking which registers, and what format the value has. + void fillJSValue(GPRReg gpr, DataFormat format = DataFormatJS) + { + ASSERT(format & DataFormatJS); + m_registerFormat = format; + u.gpr = gpr; + } + void fillInteger(GPRReg gpr) + { + m_registerFormat = DataFormatInteger; + u.gpr = gpr; + } + void fillDouble(FPRReg fpr) + { + m_registerFormat = DataFormatDouble; + u.fpr = fpr; + } + +#ifndef NDEBUG + bool alive() + { + return m_useCount; + } +#endif + +private: + // The index of the node whose result is stored in this virtual register. + // FIXME: Can we remove this? - this is currently only used when collecting + // snapshots of the RegisterBank for SpeculationCheck/EntryLocation. Could + // investigate storing NodeIndex as the name in RegsiterBank, instead of + // VirtualRegister. + NodeIndex m_nodeIndex; + uint32_t m_useCount; + DataFormat m_registerFormat; + DataFormat m_spillFormat; + bool m_canFill; + union { + GPRReg gpr; + FPRReg fpr; + } u; +}; + +} } // namespace JSC::DFG + +#endif +#endif diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp new file mode 100644 index 0000000..be3beec --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DFGGraph.h" + +#include "CodeBlock.h" + +#if ENABLE(DFG_JIT) + +namespace JSC { namespace DFG { + +#ifndef NDEBUG +void Graph::dump(CodeBlock* codeBlock) +{ + // Creates an array of stringized names. +#define STRINGIZE_DFG_OP_ENUM(opcode, flags) #opcode , + const char* dfgOpNames[] = { + FOR_EACH_DFG_OP(STRINGIZE_DFG_OP_ENUM) + }; +#undef STRINGIZE_DFG_OP_ENUM + + Node* nodes = this->begin(); + + for (size_t i = 0; i < size(); ++i) { + Node& node = nodes[i]; + NodeType op = node.op; + + unsigned refCount = node.refCount; + if (!refCount) + continue; + bool mustGenerate = node.mustGenerate(); + if (mustGenerate) + --refCount; + + // Example/explanation of dataflow dump output + // + // 14: <!2:7> GetByVal(@3, @13) + // ^1 ^2 ^3 ^4 ^5 + // + // (1) The nodeIndex of this operation. + // (2) The reference count. The number printed is the 'real' count, + // not including the 'mustGenerate' ref. If the node is + // 'mustGenerate' then the count it prefixed with '!'. + // (3) The virtual register slot assigned to this node. + // (4) The name of the operation. + // (5) The arguments to the operation. The may be of the form: + // @# - a NodeIndex referencing a prior node in the graph. + // arg# - an argument number. + // $# - the index in the CodeBlock of a constant { for numeric constants the value is displayed | for integers, in both decimal and hex }. + // id# - the index in the CodeBlock of an identifier { if codeBlock is passed to dump(), the string representation is displayed }. + // var# - the index of a var on the global object, used by GetGlobalVar/PutGlobalVar operations. + printf("% 4d:\t<%c%u:%u>\t%s(", (int)i, mustGenerate ? '!' : ' ', refCount, node.virtualRegister, dfgOpNames[op & NodeIdMask]); + if (node.child1 != NoNode) + printf("@%u", node.child1); + if (node.child2 != NoNode) + printf(", @%u", node.child2); + if (node.child3 != NoNode) + printf(", @%u", node.child3); + bool hasPrinted = node.child1 != NoNode; + + if (node.hasVarNumber()) { + printf("%svar%u", hasPrinted ? ", " : "", node.varNumber()); + hasPrinted = true; + } + if (node.hasIdentifier()) { + if (codeBlock) + printf("%sid%u{%s}", hasPrinted ? ", " : "", node.identifierNumber(), codeBlock->identifier(node.identifierNumber()).ustring().utf8().data()); + else + printf("%sid%u", hasPrinted ? ", " : "", node.identifierNumber()); + hasPrinted = true; + } + if (node.isArgument()) { + printf("%sarg%u", hasPrinted ? ", " : "", node.argumentNumber()); + hasPrinted = true; + } + if (op == Int32Constant) { + printf("%s$%u{%d|0x%08x}", hasPrinted ? ", " : "", node.constantNumber(), node.int32Constant(), node.int32Constant()); + hasPrinted = true; + } + if (op == DoubleConstant) { + printf("%s$%u{%f})", hasPrinted ? ", " : "", node.constantNumber(), node.numericConstant()); + hasPrinted = true; + } + if (op == JSConstant) { + printf("%s$%u", hasPrinted ? ", " : "", node.constantNumber()); + hasPrinted = true; + } + + printf(")\n"); + } +} +#endif + +// FIXME: Convert this method to be iterative, not recursive. +void Graph::refChildren(NodeIndex op) +{ + Node& node = at(op); + + if (node.child1 == NoNode) { + ASSERT(node.child2 == NoNode && node.child3 == NoNode); + return; + } + ref(node.child1); + + if (node.child2 == NoNode) { + ASSERT(node.child3 == NoNode); + return; + } + ref(node.child2); + + if (node.child3 == NoNode) + return; + ref(node.child3); +} + +} } // namespace JSC::DFG + +#endif diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h new file mode 100644 index 0000000..c02110e --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGGraph.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGGraph_h +#define DFGGraph_h + +#if ENABLE(DFG_JIT) + +#include <dfg/DFGNode.h> +#include <wtf/Vector.h> + +namespace JSC { + +class CodeBlock; + +namespace DFG { + +// +// === Graph === +// +// The dataflow graph is an ordered vector of nodes. +// The order may be significant for nodes with side-effects (property accesses, value conversions). +// Nodes that are 'dead' remain in the vector with refCount 0. +class Graph : public Vector<Node, 64> { +public: + // Mark a node as being referenced. + void ref(NodeIndex nodeIndex) + { + // If the value (before incrementing) was at reCount zero then we need to ref its children. + if (!at(nodeIndex).refCount++) + refChildren(nodeIndex); + } + +#ifndef NDEBUG + // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names). + void dump(CodeBlock* = 0); +#endif + +private: + // When a node's refCount goes from 0 to 1, it must (logically) recursively ref all of its children. + void refChildren(NodeIndex); +}; + +} } // namespace JSC::DFG + +#endif +#endif diff --git a/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp b/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp new file mode 100644 index 0000000..b945b5a --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp @@ -0,0 +1,563 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DFGJITCodeGenerator.h" + +#if ENABLE(DFG_JIT) + +#include "DFGNonSpeculativeJIT.h" +#include "DFGSpeculativeJIT.h" +#include "LinkBuffer.h" + +namespace JSC { namespace DFG { + +GPRReg JITCodeGenerator::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat) +{ + Node& node = m_jit.graph()[nodeIndex]; + VirtualRegister virtualRegister = node.virtualRegister; + GenerationInfo& info = m_generationInfo[virtualRegister]; + + if (info.registerFormat() == DataFormatNone) { + GPRReg gpr = allocate(); + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); + + if (node.isConstant()) { + m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); + if (isInt32Constant(nodeIndex)) { + m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), reg); + info.fillInteger(gpr); + returnFormat = DataFormatInteger; + return gpr; + } + if (isDoubleConstant(nodeIndex)) { + JSValue jsValue = jsNumber(valueOfDoubleConstant(nodeIndex)); + m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg); + } else { + ASSERT(isJSConstant(nodeIndex)); + JSValue jsValue = valueOfJSConstant(nodeIndex); + m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg); + } + } else if (node.isArgument()) { + m_gprs.retain(gpr, virtualRegister, SpillOrderArgument); + m_jit.loadPtr(m_jit.addressForArgument(m_jit.graph()[nodeIndex].argumentNumber()), reg); + } else { + ASSERT(info.spillFormat() == DataFormatJS || info.spillFormat() == DataFormatJSInteger); + m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); + m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg); + } + + // Since we statically know that we're filling an integer, and values + // in the RegisterFile are boxed, this must be DataFormatJSInteger. + // We will check this with a jitAssert below. + info.fillJSValue(gpr, DataFormatJSInteger); + unlock(gpr); + } + + switch (info.registerFormat()) { + case DataFormatNone: + // Should have filled, above. + case DataFormatJSDouble: + case DataFormatDouble: + case DataFormatJS: + case DataFormatCell: + case DataFormatJSCell: + // Should only be calling this function if we know this operand to be integer. + ASSERT_NOT_REACHED(); + + case DataFormatJSInteger: { + GPRReg gpr = info.gpr(); + m_gprs.lock(gpr); + m_jit.jitAssertIsJSInt32(gpr); + returnFormat = DataFormatJSInteger; + return gpr; + } + + case DataFormatInteger: { + GPRReg gpr = info.gpr(); + m_gprs.lock(gpr); + m_jit.jitAssertIsInt32(gpr); + returnFormat = DataFormatInteger; + return gpr; + } + } + + ASSERT_NOT_REACHED(); + return InvalidGPRReg; +} + +FPRReg JITCodeGenerator::fillDouble(NodeIndex nodeIndex) +{ + Node& node = m_jit.graph()[nodeIndex]; + VirtualRegister virtualRegister = node.virtualRegister; + GenerationInfo& info = m_generationInfo[virtualRegister]; + + if (info.registerFormat() == DataFormatNone) { + GPRReg gpr = allocate(); + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); + + if (node.isConstant()) { + if (isInt32Constant(nodeIndex)) { + // FIXME: should not be reachable? + m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), reg); + m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); + info.fillInteger(gpr); + unlock(gpr); + } else if (isDoubleConstant(nodeIndex)) { + FPRReg fpr = fprAllocate(); + m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfDoubleConstant(nodeIndex)))), reg); + m_jit.movePtrToDouble(reg, JITCompiler::fprToRegisterID(fpr)); + unlock(gpr); + + m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); + info.fillDouble(fpr); + return fpr; + } else { + // FIXME: should not be reachable? + ASSERT(isJSConstant(nodeIndex)); + JSValue jsValue = valueOfJSConstant(nodeIndex); + m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg); + m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); + info.fillJSValue(gpr, DataFormatJS); + unlock(gpr); + } + } else if (node.isArgument()) { + m_gprs.retain(gpr, virtualRegister, SpillOrderArgument); + m_jit.loadPtr(m_jit.addressForArgument(m_jit.graph()[nodeIndex].argumentNumber()), reg); + info.fillJSValue(gpr, DataFormatJS); + unlock(gpr); + } else { + DataFormat spillFormat = info.spillFormat(); + ASSERT(spillFormat & DataFormatJS); + m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); + m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg); + info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS); + unlock(gpr); + } + } + + switch (info.registerFormat()) { + case DataFormatNone: + // Should have filled, above. + case DataFormatCell: + case DataFormatJSCell: + // Should only be calling this function if we know this operand to be numeric. + ASSERT_NOT_REACHED(); + + case DataFormatJS: { + GPRReg jsValueGpr = info.gpr(); + m_gprs.lock(jsValueGpr); + FPRReg fpr = fprAllocate(); + GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register? + + JITCompiler::RegisterID jsValueReg = JITCompiler::gprToRegisterID(jsValueGpr); + JITCompiler::FPRegisterID fpReg = JITCompiler::fprToRegisterID(fpr); + JITCompiler::RegisterID tempReg = JITCompiler::gprToRegisterID(tempGpr); + + JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueReg, JITCompiler::tagTypeNumberRegister); + + m_jit.jitAssertIsJSDouble(jsValueGpr); + + // First, if we get here we have a double encoded as a JSValue + m_jit.move(jsValueReg, tempReg); + m_jit.addPtr(JITCompiler::tagTypeNumberRegister, tempReg); + m_jit.movePtrToDouble(tempReg, fpReg); + JITCompiler::Jump hasUnboxedDouble = m_jit.jump(); + + // Finally, handle integers. + isInteger.link(&m_jit); + m_jit.convertInt32ToDouble(jsValueReg, fpReg); + hasUnboxedDouble.link(&m_jit); + + m_gprs.release(jsValueGpr); + m_gprs.unlock(jsValueGpr); + m_gprs.unlock(tempGpr); + m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); + info.fillDouble(fpr); + return fpr; + } + + case DataFormatJSInteger: + case DataFormatInteger: { + FPRReg fpr = fprAllocate(); + GPRReg gpr = info.gpr(); + m_gprs.lock(gpr); + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); + JITCompiler::FPRegisterID fpReg = JITCompiler::fprToRegisterID(fpr); + + m_jit.convertInt32ToDouble(reg, fpReg); + + m_gprs.release(gpr); + m_gprs.unlock(gpr); + m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); + info.fillDouble(fpr); + return fpr; + } + + // Unbox the double + case DataFormatJSDouble: { + GPRReg gpr = info.gpr(); + FPRReg fpr = unboxDouble(gpr); + + m_gprs.release(gpr); + m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); + + info.fillDouble(fpr); + return fpr; + } + + case DataFormatDouble: { + FPRReg fpr = info.fpr(); + m_fprs.lock(fpr); + return fpr; + } + } + + ASSERT_NOT_REACHED(); + return InvalidFPRReg; +} + +GPRReg JITCodeGenerator::fillJSValue(NodeIndex nodeIndex) +{ + Node& node = m_jit.graph()[nodeIndex]; + VirtualRegister virtualRegister = node.virtualRegister; + GenerationInfo& info = m_generationInfo[virtualRegister]; + + switch (info.registerFormat()) { + case DataFormatNone: { + GPRReg gpr = allocate(); + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); + + if (node.isConstant()) { + if (isInt32Constant(nodeIndex)) { + info.fillJSValue(gpr, DataFormatJSInteger); + JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex)); + m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg); + } else if (isDoubleConstant(nodeIndex)) { + info.fillJSValue(gpr, DataFormatJSDouble); + JSValue jsValue(JSValue::EncodeAsDouble, valueOfDoubleConstant(nodeIndex)); + m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg); + } else { + ASSERT(isJSConstant(nodeIndex)); + JSValue jsValue = valueOfJSConstant(nodeIndex); + m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), reg); + info.fillJSValue(gpr, DataFormatJS); + } + + m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); + } else if (node.isArgument()) { + m_gprs.retain(gpr, virtualRegister, SpillOrderArgument); + m_jit.loadPtr(m_jit.addressForArgument(m_jit.graph()[nodeIndex].argumentNumber()), reg); + info.fillJSValue(gpr, DataFormatJS); + } else { + DataFormat spillFormat = info.spillFormat(); + ASSERT(spillFormat & DataFormatJS); + m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); + m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg); + info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS); + } + return gpr; + } + + case DataFormatInteger: { + GPRReg gpr = info.gpr(); + m_gprs.lock(gpr); + m_jit.orPtr(JITCompiler::tagTypeNumberRegister, JITCompiler::gprToRegisterID(gpr)); + info.fillJSValue(gpr, DataFormatJSInteger); + return gpr; + } + + case DataFormatDouble: { + FPRReg fpr = info.fpr(); + GPRReg gpr = boxDouble(fpr); + + // Update all info + info.fillJSValue(gpr, DataFormatJSDouble); + m_fprs.release(fpr); + m_gprs.retain(gpr, virtualRegister, SpillOrderJS); + + return gpr; + } + + case DataFormatCell: + // No retag required on JSVALUE64! + case DataFormatJS: + case DataFormatJSInteger: + case DataFormatJSDouble: + case DataFormatJSCell: { + GPRReg gpr = info.gpr(); + m_gprs.lock(gpr); + return gpr; + } + } + + ASSERT_NOT_REACHED(); + return InvalidGPRReg; +} + +void JITCodeGenerator::useChildren(Node& node) +{ + NodeIndex child1 = node.child1; + if (child1 == NoNode) { + ASSERT(node.child2 == NoNode && node.child3 == NoNode); + return; + } + use(child1); + + NodeIndex child2 = node.child2; + if (child2 == NoNode) { + ASSERT(node.child3 == NoNode); + return; + } + use(child2); + + NodeIndex child3 = node.child3; + if (child3 == NoNode) + return; + use(child3); +} + +#ifndef NDEBUG +static const char* dataFormatString(DataFormat format) +{ + // These values correspond to the DataFormat enum. + const char* strings[] = { + "[ ]", + "[ i]", + "[ d]", + "[ c]", + "Err!", + "Err!", + "Err!", + "Err!", + "[J ]", + "[Ji]", + "[Jd]", + "[Jc]", + "Err!", + "Err!", + "Err!", + "Err!", + }; + return strings[format]; +} + +void JITCodeGenerator::dump(const char* label) +{ + if (label) + fprintf(stderr, "<%s>\n", label); + + fprintf(stderr, " gprs:\n"); + m_gprs.dump(); + fprintf(stderr, " fprs:\n"); + m_fprs.dump(); + fprintf(stderr, " VirtualRegisters:\n"); + for (unsigned i = 0; i < m_generationInfo.size(); ++i) { + GenerationInfo& info = m_generationInfo[i]; + if (info.alive()) + fprintf(stderr, " % 3d:%s%s\n", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat())); + else + fprintf(stderr, " % 3d:[__][__]\n", i); + } + if (label) + fprintf(stderr, "</%s>\n", label); +} +#endif + + +#if DFG_CONSISTENCY_CHECK +void JITCodeGenerator::checkConsistency() +{ + VirtualRegister grpContents[numberOfGPRs]; + VirtualRegister frpContents[numberOfFPRs]; + + for (unsigned i = 0; i < numberOfGPRs; ++i) + grpContents[i] = InvalidVirtualRegister; + for (unsigned i = 0; i < numberOfFPRs; ++i) + frpContents[i] = InvalidVirtualRegister; + for (unsigned i = 0; i < m_generationInfo.size(); ++i) { + GenerationInfo& info = m_generationInfo[i]; + if (!info.alive()) + continue; + switch (info.registerFormat()) { + case DataFormatNone: + break; + case DataFormatInteger: + case DataFormatCell: + case DataFormatJS: + case DataFormatJSInteger: + case DataFormatJSDouble: + case DataFormatJSCell: { + GPRReg gpr = info.gpr(); + ASSERT(gpr != InvalidGPRReg); + grpContents[gpr] = (VirtualRegister)i; + break; + } + case DataFormatDouble: { + FPRReg fpr = info.fpr(); + ASSERT(fpr != InvalidFPRReg); + frpContents[fpr] = (VirtualRegister)i; + break; + } + } + } + + for (GPRReg i = gpr0; i < numberOfGPRs; next(i)) { + if (m_gprs.isLocked(i) || m_gprs.name(i) != grpContents[i]) { + dump(); + CRASH(); + } + } + for (FPRReg i = fpr0; i < numberOfFPRs; next(i)) { + if (m_fprs.isLocked(i) || m_fprs.name(i) != frpContents[i]) { + dump(); + CRASH(); + } + } +} +#endif + +GPRTemporary::GPRTemporary(JITCodeGenerator* jit) + : m_jit(jit) + , m_gpr(InvalidGPRReg) +{ + m_gpr = m_jit->allocate(); +} + +GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1) + : m_jit(jit) + , m_gpr(InvalidGPRReg) +{ + // locking into a register may free for reuse! + op1.gpr(); + if (m_jit->canReuse(op1.index())) + m_gpr = m_jit->reuse(op1.gpr()); + else + m_gpr = m_jit->allocate(); +} + +GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1, SpeculateIntegerOperand& op2) + : m_jit(jit) + , m_gpr(InvalidGPRReg) +{ + // locking into a register may free for reuse! + op1.gpr(); + op2.gpr(); + if (m_jit->canReuse(op1.index())) + m_gpr = m_jit->reuse(op1.gpr()); + else if (m_jit->canReuse(op2.index())) + m_gpr = m_jit->reuse(op2.gpr()); + else + m_gpr = m_jit->allocate(); +} + +GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1) + : m_jit(jit) + , m_gpr(InvalidGPRReg) +{ + // locking into a register may free for reuse! + op1.gpr(); + if (m_jit->canReuse(op1.index())) + m_gpr = m_jit->reuse(op1.gpr()); + else + m_gpr = m_jit->allocate(); +} + +GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1, IntegerOperand& op2) + : m_jit(jit) + , m_gpr(InvalidGPRReg) +{ + // locking into a register may free for reuse! + op1.gpr(); + op2.gpr(); + if (m_jit->canReuse(op1.index())) + m_gpr = m_jit->reuse(op1.gpr()); + else if (m_jit->canReuse(op2.index())) + m_gpr = m_jit->reuse(op2.gpr()); + else + m_gpr = m_jit->allocate(); +} + +GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateCellOperand& op1) + : m_jit(jit) + , m_gpr(InvalidGPRReg) +{ + // locking into a register may free for reuse! + op1.gpr(); + if (m_jit->canReuse(op1.index())) + m_gpr = m_jit->reuse(op1.gpr()); + else + m_gpr = m_jit->allocate(); +} + +GPRTemporary::GPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1) + : m_jit(jit) + , m_gpr(InvalidGPRReg) +{ + // locking into a register may free for reuse! + op1.gpr(); + if (m_jit->canReuse(op1.index())) + m_gpr = m_jit->reuse(op1.gpr()); + else + m_gpr = m_jit->allocate(); +} + +FPRTemporary::FPRTemporary(JITCodeGenerator* jit) + : m_jit(jit) + , m_fpr(InvalidFPRReg) +{ + m_fpr = m_jit->fprAllocate(); +} + +FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1) + : m_jit(jit) + , m_fpr(InvalidFPRReg) +{ + // locking into a register may free for reuse! + op1.fpr(); + if (m_jit->canReuse(op1.index())) + m_fpr = m_jit->reuse(op1.fpr()); + else + m_fpr = m_jit->fprAllocate(); +} + +FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1, DoubleOperand& op2) + : m_jit(jit) + , m_fpr(InvalidFPRReg) +{ + // locking into a register may free for reuse! + op1.fpr(); + op2.fpr(); + if (m_jit->canReuse(op1.index())) + m_fpr = m_jit->reuse(op1.fpr()); + else if (m_jit->canReuse(op2.index())) + m_fpr = m_jit->reuse(op2.fpr()); + else + m_fpr = m_jit->fprAllocate(); +} + +} } // namespace JSC::DFG + +#endif diff --git a/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h b/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h new file mode 100644 index 0000000..a84cdc6 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h @@ -0,0 +1,955 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGJITCodeGenerator_h +#define DFGJITCodeGenerator_h + +#if ENABLE(DFG_JIT) + +#include "CodeBlock.h" +#include <dfg/DFGGenerationInfo.h> +#include <dfg/DFGGraph.h> +#include <dfg/DFGJITCompiler.h> +#include <dfg/DFGOperations.h> +#include <dfg/DFGRegisterBank.h> + +namespace JSC { namespace DFG { + +class SpeculateIntegerOperand; +class SpeculateStrictInt32Operand; +class SpeculateCellOperand; + + +// === JITCodeGenerator === +// +// This class provides common infrastructure used by the speculative & +// non-speculative JITs. Provides common mechanisms for virtual and +// physical register management, calls out from JIT code to helper +// functions, etc. +class JITCodeGenerator { +protected: + typedef MacroAssembler::TrustedImm32 TrustedImm32; + typedef MacroAssembler::Imm32 Imm32; + + // These constants are used to set priorities for spill order for + // the register allocator. + enum SpillOrder { + SpillOrderNone, + SpillOrderConstant = 1, // no spill, and cheap fill + SpillOrderSpilled = 2, // no spill + SpillOrderArgument = 3, // no spill, but we may lose typeinfo + SpillOrderJS = 4, // needs spill + SpillOrderCell = 4, // needs spill + SpillOrderInteger = 5, // needs spill and box + SpillOrderDouble = 6, // needs spill and convert + SpillOrderMax + }; + + +public: + GPRReg fillInteger(NodeIndex, DataFormat& returnFormat); + FPRReg fillDouble(NodeIndex); + GPRReg fillJSValue(NodeIndex); + + // lock and unlock GPR & FPR registers. + void lock(GPRReg reg) + { + m_gprs.lock(reg); + } + void lock(FPRReg reg) + { + m_fprs.lock(reg); + } + void unlock(GPRReg reg) + { + m_gprs.unlock(reg); + } + void unlock(FPRReg reg) + { + m_fprs.unlock(reg); + } + + // Used to check whether a child node is on its last use, + // and its machine registers may be reused. + bool canReuse(NodeIndex nodeIndex) + { + VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister; + GenerationInfo& info = m_generationInfo[virtualRegister]; + return info.canReuse(); + } + GPRReg reuse(GPRReg reg) + { + m_gprs.lock(reg); + return reg; + } + FPRReg reuse(FPRReg reg) + { + m_fprs.lock(reg); + return reg; + } + + // Allocate a gpr/fpr. + GPRReg allocate() + { + VirtualRegister spillMe; + GPRReg gpr = m_gprs.allocate(spillMe); + if (spillMe != InvalidVirtualRegister) + spill(spillMe); + return gpr; + } + FPRReg fprAllocate() + { + VirtualRegister spillMe; + FPRReg fpr = m_fprs.allocate(spillMe); + if (spillMe != InvalidVirtualRegister) + spill(spillMe); + return fpr; + } + + // Check whether a VirtualRegsiter is currently in a machine register. + // We use this when filling operands to fill those that are already in + // machine registers first (by locking VirtualRegsiters that are already + // in machine register before filling those that are not we attempt to + // avoid spilling values we will need immediately). + bool isFilled(NodeIndex nodeIndex) + { + VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister; + GenerationInfo& info = m_generationInfo[virtualRegister]; + return info.registerFormat() != DataFormatNone; + } + bool isFilledDouble(NodeIndex nodeIndex) + { + VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister; + GenerationInfo& info = m_generationInfo[virtualRegister]; + return info.registerFormat() == DataFormatDouble; + } + +protected: + JITCodeGenerator(JITCompiler& jit, bool isSpeculative) + : m_jit(jit) + , m_isSpeculative(isSpeculative) + , m_compileIndex(0) + , m_generationInfo(m_jit.codeBlock()->m_numCalleeRegisters) + { + } + + // These methods convert between doubles, and doubles boxed and JSValues. + GPRReg boxDouble(FPRReg fpr, GPRReg gpr) + { + JITCompiler::FPRegisterID fpReg = JITCompiler::fprToRegisterID(fpr); + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); + m_jit.moveDoubleToPtr(fpReg, reg); + m_jit.subPtr(JITCompiler::tagTypeNumberRegister, reg); + return gpr; + } + FPRReg unboxDouble(GPRReg gpr, FPRReg fpr) + { + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); + JITCompiler::FPRegisterID fpReg = JITCompiler::fprToRegisterID(fpr); + m_jit.addPtr(JITCompiler::tagTypeNumberRegister, reg); + m_jit.movePtrToDouble(reg, fpReg); + return fpr; + } + GPRReg boxDouble(FPRReg fpr) + { + return boxDouble(fpr, allocate()); + } + FPRReg unboxDouble(GPRReg gpr) + { + return unboxDouble(gpr, fprAllocate()); + } + + // Called on an operand once it has been consumed by a parent node. + void use(NodeIndex nodeIndex) + { + VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister; + GenerationInfo& info = m_generationInfo[virtualRegister]; + + // use() returns true when the value becomes dead, and any + // associated resources may be freed. + if (!info.use()) + return; + + // Release the associated machine registers. + DataFormat registerFormat = info.registerFormat(); + if (registerFormat == DataFormatDouble) + m_fprs.release(info.fpr()); + else if (registerFormat != DataFormatNone) + m_gprs.release(info.gpr()); + } + + // Spill a VirtualRegister to the RegisterFile. + void spill(VirtualRegister spillMe) + { + GenerationInfo& info = m_generationInfo[spillMe]; + + // Check the GenerationInfo to see if this value need writing + // to the RegisterFile - if not, mark it as spilled & return. + if (!info.needsSpill()) { + info.setSpilled(); + return; + } + + DataFormat spillFormat = info.registerFormat(); + if (spillFormat == DataFormatDouble) { + // All values are spilled as JSValues, so box the double via a temporary gpr. + GPRReg gpr = boxDouble(info.fpr()); + m_jit.storePtr(JITCompiler::gprToRegisterID(gpr), JITCompiler::addressFor(spillMe)); + unlock(gpr); + info.spill(DataFormatJSDouble); + return; + } + + // The following code handles JSValues, int32s, and cells. + ASSERT(spillFormat == DataFormatInteger || spillFormat == DataFormatCell || spillFormat & DataFormatJS); + + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(info.gpr()); + // We need to box int32 and cell values ... + // but on JSVALUE64 boxing a cell is a no-op! + if (spillFormat == DataFormatInteger) + m_jit.orPtr(JITCompiler::tagTypeNumberRegister, reg); + + // Spill the value, and record it as spilled in its boxed form. + m_jit.storePtr(reg, JITCompiler::addressFor(spillMe)); + info.spill((DataFormat)(spillFormat | DataFormatJS)); + } + + // Checks/accessors for constant values. + bool isInt32Constant(NodeIndex nodeIndex) { return m_jit.isInt32Constant(nodeIndex); } + bool isDoubleConstant(NodeIndex nodeIndex) { return m_jit.isDoubleConstant(nodeIndex); } + bool isJSConstant(NodeIndex nodeIndex) { return m_jit.isJSConstant(nodeIndex); } + int32_t valueOfInt32Constant(NodeIndex nodeIndex) { return m_jit.valueOfInt32Constant(nodeIndex); } + double valueOfDoubleConstant(NodeIndex nodeIndex) { return m_jit.valueOfDoubleConstant(nodeIndex); } + JSValue valueOfJSConstant(NodeIndex nodeIndex) { return m_jit.valueOfJSConstant(nodeIndex); } + + Identifier* identifier(unsigned index) + { + return &m_jit.codeBlock()->identifier(index); + } + + // Spill all VirtualRegisters back to the RegisterFile. + void flushRegisters() + { + for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) { + VirtualRegister name = m_gprs.name(gpr); + if (name != InvalidVirtualRegister) { + spill(name); + m_gprs.release(gpr); + } + } + for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) { + VirtualRegister name = m_fprs.name(fpr); + if (name != InvalidVirtualRegister) { + spill(name); + m_fprs.release(fpr); + } + } + } + +#ifndef NDEBUG + // Used to ASSERT flushRegisters() has been called prior to + // calling out from JIT code to a C helper function. + bool isFlushed() + { + for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) { + VirtualRegister name = m_gprs.name(gpr); + if (name != InvalidVirtualRegister) + return false; + } + for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) { + VirtualRegister name = m_fprs.name(fpr); + if (name != InvalidVirtualRegister) + return false; + } + return true; + } +#endif + + // Get the JSValue representation of a constant. + JSValue constantAsJSValue(NodeIndex nodeIndex) + { + Node& node = m_jit.graph()[nodeIndex]; + if (isInt32Constant(nodeIndex)) + return jsNumber(node.int32Constant()); + if (isDoubleConstant(nodeIndex)) + return JSValue(JSValue::EncodeAsDouble, node.numericConstant()); + ASSERT(isJSConstant(nodeIndex)); + return valueOfJSConstant(nodeIndex); + } + MacroAssembler::ImmPtr constantAsJSValueAsImmPtr(NodeIndex nodeIndex) + { + return MacroAssembler::ImmPtr(JSValue::encode(constantAsJSValue(nodeIndex))); + } + + // Helper functions to enable code sharing in implementations of bit/shift ops. + void bitOp(NodeType op, int32_t imm, MacroAssembler::RegisterID op1, MacroAssembler::RegisterID result) + { + switch (op) { + case BitAnd: + m_jit.and32(Imm32(imm), op1, result); + break; + case BitOr: + m_jit.or32(Imm32(imm), op1, result); + break; + case BitXor: + m_jit.xor32(Imm32(imm), op1, result); + break; + default: + ASSERT_NOT_REACHED(); + } + } + void bitOp(NodeType op, MacroAssembler::RegisterID op1, MacroAssembler::RegisterID op2, MacroAssembler::RegisterID result) + { + switch (op) { + case BitAnd: + m_jit.and32(op1, op2, result); + break; + case BitOr: + m_jit.or32(op1, op2, result); + break; + case BitXor: + m_jit.xor32(op1, op2, result); + break; + default: + ASSERT_NOT_REACHED(); + } + } + void shiftOp(NodeType op, MacroAssembler::RegisterID op1, int32_t shiftAmount, MacroAssembler::RegisterID result) + { + switch (op) { + case BitRShift: + m_jit.rshift32(op1, Imm32(shiftAmount), result); + break; + case BitLShift: + m_jit.lshift32(op1, Imm32(shiftAmount), result); + break; + case BitURShift: + m_jit.urshift32(op1, Imm32(shiftAmount), result); + break; + default: + ASSERT_NOT_REACHED(); + } + } + void shiftOp(NodeType op, MacroAssembler::RegisterID op1, MacroAssembler::RegisterID shiftAmount, MacroAssembler::RegisterID result) + { + switch (op) { + case BitRShift: + m_jit.rshift32(op1, shiftAmount, result); + break; + case BitLShift: + m_jit.lshift32(op1, shiftAmount, result); + break; + case BitURShift: + m_jit.urshift32(op1, shiftAmount, result); + break; + default: + ASSERT_NOT_REACHED(); + } + } + + // Called once a node has completed code generation but prior to setting + // its result, to free up its children. (This must happen prior to setting + // the nodes result, since the node may have the same VirtualRegister as + // a child, and as such will use the same GeneratioInfo). + void useChildren(Node&); + + // These method called to initialize the the GenerationInfo + // to describe the result of an operation. + void integerResult(GPRReg reg, NodeIndex nodeIndex, DataFormat format = DataFormatInteger) + { + Node& node = m_jit.graph()[nodeIndex]; + useChildren(node); + + VirtualRegister virtualRegister = node.virtualRegister; + GenerationInfo& info = m_generationInfo[virtualRegister]; + + if (format == DataFormatInteger) { + m_jit.jitAssertIsInt32(reg); + m_gprs.retain(reg, virtualRegister, SpillOrderInteger); + info.initInteger(nodeIndex, node.refCount, reg); + } else { + ASSERT(format == DataFormatJSInteger); + m_jit.jitAssertIsJSInt32(reg); + m_gprs.retain(reg, virtualRegister, SpillOrderJS); + info.initJSValue(nodeIndex, node.refCount, reg, format); + } + } + void noResult(NodeIndex nodeIndex) + { + Node& node = m_jit.graph()[nodeIndex]; + useChildren(node); + + VirtualRegister virtualRegister = node.virtualRegister; + GenerationInfo& info = m_generationInfo[virtualRegister]; + info.initNone(nodeIndex, node.refCount); + } + void cellResult(GPRReg reg, NodeIndex nodeIndex) + { + Node& node = m_jit.graph()[nodeIndex]; + useChildren(node); + + VirtualRegister virtualRegister = node.virtualRegister; + m_gprs.retain(reg, virtualRegister, SpillOrderCell); + GenerationInfo& info = m_generationInfo[virtualRegister]; + info.initCell(nodeIndex, node.refCount, reg); + } + void jsValueResult(GPRReg reg, NodeIndex nodeIndex, DataFormat format = DataFormatJS) + { + if (format == DataFormatJSInteger) + m_jit.jitAssertIsJSInt32(reg); + + Node& node = m_jit.graph()[nodeIndex]; + useChildren(node); + + VirtualRegister virtualRegister = node.virtualRegister; + m_gprs.retain(reg, virtualRegister, SpillOrderJS); + GenerationInfo& info = m_generationInfo[virtualRegister]; + info.initJSValue(nodeIndex, node.refCount, reg, format); + } + void doubleResult(FPRReg reg, NodeIndex nodeIndex) + { + Node& node = m_jit.graph()[nodeIndex]; + useChildren(node); + + VirtualRegister virtualRegister = node.virtualRegister; + m_fprs.retain(reg, virtualRegister, SpillOrderDouble); + GenerationInfo& info = m_generationInfo[virtualRegister]; + info.initDouble(nodeIndex, node.refCount, reg); + } + void initConstantInfo(NodeIndex nodeIndex) + { + ASSERT(isInt32Constant(nodeIndex) || isDoubleConstant(nodeIndex) || isJSConstant(nodeIndex)); + Node& node = m_jit.graph()[nodeIndex]; + m_generationInfo[node.virtualRegister].initConstant(nodeIndex, node.refCount); + } + void initArgumentInfo(NodeIndex nodeIndex) + { + Node& node = m_jit.graph()[nodeIndex]; + m_generationInfo[node.virtualRegister].initArgument(nodeIndex, node.refCount); + } + + // These methods used to sort arguments into the correct registers. + template<GPRReg destA, GPRReg destB> + void setupTwoStubArgs(GPRReg srcA, GPRReg srcB) + { + // Assuming that srcA != srcB, there are 7 interesting states the registers may be in: + // (1) both are already in arg regs, the right way around. + // (2) both are already in arg regs, the wrong way around. + // (3) neither are currently in arg registers. + // (4) srcA in in its correct reg. + // (5) srcA in in the incorrect reg. + // (6) srcB in in its correct reg. + // (7) srcB in in the incorrect reg. + // + // The trivial approach is to simply emit two moves, to put srcA in place then srcB in + // place (the MacroAssembler will omit redundant moves). This apporach will be safe in + // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2 + // (requires a swap) and 7 (must move srcB first, to avoid trampling.) + + if (srcB != destA) { + // Handle the easy cases - two simple moves. + m_jit.move(JITCompiler::gprToRegisterID(srcA), JITCompiler::gprToRegisterID(destA)); + m_jit.move(JITCompiler::gprToRegisterID(srcB), JITCompiler::gprToRegisterID(destB)); + } else if (srcA != destB) { + // Handle the non-swap case - just put srcB in place first. + m_jit.move(JITCompiler::gprToRegisterID(srcB), JITCompiler::gprToRegisterID(destB)); + m_jit.move(JITCompiler::gprToRegisterID(srcA), JITCompiler::gprToRegisterID(destA)); + } else + m_jit.swap(JITCompiler::gprToRegisterID(destB), JITCompiler::gprToRegisterID(destB)); + } + template<FPRReg destA, FPRReg destB> + void setupTwoStubArgs(FPRReg srcA, FPRReg srcB) + { + // Assuming that srcA != srcB, there are 7 interesting states the registers may be in: + // (1) both are already in arg regs, the right way around. + // (2) both are already in arg regs, the wrong way around. + // (3) neither are currently in arg registers. + // (4) srcA in in its correct reg. + // (5) srcA in in the incorrect reg. + // (6) srcB in in its correct reg. + // (7) srcB in in the incorrect reg. + // + // The trivial approach is to simply emit two moves, to put srcA in place then srcB in + // place (the MacroAssembler will omit redundant moves). This apporach will be safe in + // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2 + // (requires a swap) and 7 (must move srcB first, to avoid trampling.) + + if (srcB != destA) { + // Handle the easy cases - two simple moves. + m_jit.moveDouble(JITCompiler::fprToRegisterID(srcA), JITCompiler::fprToRegisterID(destA)); + m_jit.moveDouble(JITCompiler::fprToRegisterID(srcB), JITCompiler::fprToRegisterID(destB)); + return; + } + + if (srcA != destB) { + // Handle the non-swap case - just put srcB in place first. + m_jit.moveDouble(JITCompiler::fprToRegisterID(srcB), JITCompiler::fprToRegisterID(destB)); + m_jit.moveDouble(JITCompiler::fprToRegisterID(srcA), JITCompiler::fprToRegisterID(destA)); + return; + } + + ASSERT(srcB == destA && srcA == destB); + // Need to swap; pick a temporary register. + FPRReg temp; + if (destA != JITCompiler::argumentFPR3 && destA != JITCompiler::argumentFPR3) + temp = JITCompiler::argumentFPR3; + else if (destA != JITCompiler::argumentFPR2 && destA != JITCompiler::argumentFPR2) + temp = JITCompiler::argumentFPR2; + else { + ASSERT(destA != JITCompiler::argumentFPR1 && destA != JITCompiler::argumentFPR1); + temp = JITCompiler::argumentFPR1; + } + m_jit.moveDouble(JITCompiler::fprToRegisterID(destA), JITCompiler::fprToRegisterID(temp)); + m_jit.moveDouble(JITCompiler::fprToRegisterID(destB), JITCompiler::fprToRegisterID(destA)); + m_jit.moveDouble(JITCompiler::fprToRegisterID(temp), JITCompiler::fprToRegisterID(destB)); + } + void setupStubArguments(GPRReg arg1, GPRReg arg2) + { + setupTwoStubArgs<JITCompiler::argumentGPR1, JITCompiler::argumentGPR2>(arg1, arg2); + } + void setupStubArguments(GPRReg arg1, GPRReg arg2, GPRReg arg3) + { + // If neither of arg2/arg3 are in our way, then we can move arg1 into place. + // Then we can use setupTwoStubArgs to fix arg2/arg3. + if (arg2 != JITCompiler::argumentGPR1 && arg3 != JITCompiler::argumentGPR1) { + m_jit.move(JITCompiler::gprToRegisterID(arg1), JITCompiler::argumentRegister1); + setupTwoStubArgs<JITCompiler::argumentGPR2, JITCompiler::argumentGPR3>(arg2, arg3); + return; + } + + // If neither of arg1/arg3 are in our way, then we can move arg2 into place. + // Then we can use setupTwoStubArgs to fix arg1/arg3. + if (arg1 != JITCompiler::argumentGPR2 && arg3 != JITCompiler::argumentGPR2) { + m_jit.move(JITCompiler::gprToRegisterID(arg2), JITCompiler::argumentRegister2); + setupTwoStubArgs<JITCompiler::argumentGPR1, JITCompiler::argumentGPR3>(arg1, arg3); + return; + } + + // If neither of arg1/arg2 are in our way, then we can move arg3 into place. + // Then we can use setupTwoStubArgs to fix arg1/arg2. + if (arg1 != JITCompiler::argumentGPR3 && arg2 != JITCompiler::argumentGPR3) { + m_jit.move(JITCompiler::gprToRegisterID(arg3), JITCompiler::argumentRegister3); + setupTwoStubArgs<JITCompiler::argumentGPR1, JITCompiler::argumentGPR2>(arg1, arg2); + return; + } + + // If we get here, we haven't been able to move any of arg1/arg2/arg3. + // Since all three are blocked, then all three must already be in the argument register. + // But are they in the right ones? + + // First, ensure arg1 is in place. + if (arg1 != JITCompiler::argumentGPR1) { + m_jit.swap(JITCompiler::gprToRegisterID(arg1), JITCompiler::argumentRegister1); + + // If arg1 wasn't in argumentGPR1, one of arg2/arg3 must be. + ASSERT(arg2 == JITCompiler::argumentGPR1 || arg3 == JITCompiler::argumentGPR1); + // If arg2 was in argumentGPR1 it no longer is (due to the swap). + // Otherwise arg3 must have been. Mark him as moved. + if (arg2 == JITCompiler::argumentGPR1) + arg2 = arg1; + else + arg3 = arg1; + } + + // Either arg2 & arg3 need swapping, or we're all done. + ASSERT((arg2 == JITCompiler::argumentGPR2 || arg3 == JITCompiler::argumentGPR3) + || (arg2 == JITCompiler::argumentGPR3 || arg3 == JITCompiler::argumentGPR2)); + + if (arg2 != JITCompiler::argumentGPR2) + m_jit.swap(JITCompiler::argumentRegister2, JITCompiler::argumentRegister3); + } + + // These methods add calls to C++ helper functions. + void callOperation(J_DFGOperation_EJP operation, GPRReg result, GPRReg arg1, void* pointer) + { + ASSERT(isFlushed()); + + m_jit.move(JITCompiler::gprToRegisterID(arg1), JITCompiler::argumentRegister1); + m_jit.move(JITCompiler::TrustedImmPtr(pointer), JITCompiler::argumentRegister2); + m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0); + + appendCallWithExceptionCheck(operation); + m_jit.move(JITCompiler::returnValueRegister, JITCompiler::gprToRegisterID(result)); + } + void callOperation(J_DFGOperation_EJI operation, GPRReg result, GPRReg arg1, Identifier* identifier) + { + callOperation((J_DFGOperation_EJP)operation, result, arg1, identifier); + } + void callOperation(J_DFGOperation_EJ operation, GPRReg result, GPRReg arg1) + { + ASSERT(isFlushed()); + + m_jit.move(JITCompiler::gprToRegisterID(arg1), JITCompiler::argumentRegister1); + m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0); + + appendCallWithExceptionCheck(operation); + m_jit.move(JITCompiler::returnValueRegister, JITCompiler::gprToRegisterID(result)); + } + void callOperation(J_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2) + { + ASSERT(isFlushed()); + + setupStubArguments(arg1, arg2); + m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0); + + appendCallWithExceptionCheck(operation); + m_jit.move(JITCompiler::returnValueRegister, JITCompiler::gprToRegisterID(result)); + } + void callOperation(V_DFGOperation_EJJP operation, GPRReg arg1, GPRReg arg2, void* pointer) + { + ASSERT(isFlushed()); + + setupStubArguments(arg1, arg2); + m_jit.move(JITCompiler::TrustedImmPtr(pointer), JITCompiler::argumentRegister3); + m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0); + + appendCallWithExceptionCheck(operation); + } + void callOperation(V_DFGOperation_EJJI operation, GPRReg arg1, GPRReg arg2, Identifier* identifier) + { + callOperation((V_DFGOperation_EJJP)operation, arg1, arg2, identifier); + } + void callOperation(V_DFGOperation_EJJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3) + { + ASSERT(isFlushed()); + + setupStubArguments(arg1, arg2, arg3); + m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0); + + appendCallWithExceptionCheck(operation); + } + void callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2) + { + ASSERT(isFlushed()); + + setupTwoStubArgs<JITCompiler::argumentFPR0, JITCompiler::argumentFPR1>(arg1, arg2); + + m_jit.appendCall(operation); + m_jit.moveDouble(JITCompiler::fpReturnValueRegister, JITCompiler::fprToRegisterID(result)); + } + + void appendCallWithExceptionCheck(const FunctionPtr& function) + { + m_jit.appendCallWithExceptionCheck(function, m_jit.graph()[m_compileIndex].exceptionInfo); + } + +#ifndef NDEBUG + void dump(const char* label = 0); +#endif + +#if DFG_CONSISTENCY_CHECK + void checkConsistency(); +#else + void checkConsistency() {} +#endif + + // The JIT, while also provides MacroAssembler functionality. + JITCompiler& m_jit; + // This flag is used to distinguish speculative and non-speculative + // code generation. This is significant when filling spilled values + // from the RegisterFile. When spilling we attempt to store information + // as to the type of boxed value being stored (int32, double, cell), and + // when filling on the speculative path we will retrieve this type info + // where available. On the non-speculative path, however, we cannot rely + // on the spill format info, since the a value being loaded might have + // been spilled by either the speculative or non-speculative paths (where + // we entered the non-speculative path on an intervening bail-out), and + // the value may have been boxed differently on the two paths. + bool m_isSpeculative; + // The current node being generated. + NodeIndex m_compileIndex; + // Virtual and physical register maps. + Vector<GenerationInfo, 32> m_generationInfo; + RegisterBank<GPRReg, numberOfGPRs, SpillOrder, SpillOrderNone, SpillOrderMax> m_gprs; + RegisterBank<FPRReg, numberOfFPRs, SpillOrder, SpillOrderNone, SpillOrderMax> m_fprs; +}; + +// === Operand types === +// +// IntegerOperand, DoubleOperand and JSValueOperand. +// +// These classes are used to lock the operands to a node into machine +// registers. These classes implement of pattern of locking a value +// into register at the point of construction only if it is already in +// registers, and otherwise loading it lazily at the point it is first +// used. We do so in order to attempt to avoid spilling one operand +// in order to make space available for another. + +class IntegerOperand { +public: + explicit IntegerOperand(JITCodeGenerator* jit, NodeIndex index) + : m_jit(jit) + , m_index(index) + , m_gprOrInvalid(InvalidGPRReg) +#ifndef NDEBUG + , m_format(DataFormatNone) +#endif + { + ASSERT(m_jit); + if (jit->isFilled(index)) + gpr(); + } + + ~IntegerOperand() + { + ASSERT(m_gprOrInvalid != InvalidGPRReg); + m_jit->unlock(m_gprOrInvalid); + } + + NodeIndex index() const + { + return m_index; + } + + GPRReg gpr() + { + if (m_gprOrInvalid == InvalidGPRReg) + m_gprOrInvalid = m_jit->fillInteger(index(), m_format); + return m_gprOrInvalid; + } + + DataFormat format() + { + gpr(); // m_format is set when m_gpr is locked. + ASSERT(m_format == DataFormatInteger || m_format == DataFormatJSInteger); + return m_format; + } + + MacroAssembler::RegisterID registerID() + { + return JITCompiler::gprToRegisterID(gpr()); + } + +private: + JITCodeGenerator* m_jit; + NodeIndex m_index; + GPRReg m_gprOrInvalid; + DataFormat m_format; +}; + +class DoubleOperand { +public: + explicit DoubleOperand(JITCodeGenerator* jit, NodeIndex index) + : m_jit(jit) + , m_index(index) + , m_fprOrInvalid(InvalidFPRReg) + { + ASSERT(m_jit); + if (jit->isFilledDouble(index)) + fpr(); + } + + ~DoubleOperand() + { + ASSERT(m_fprOrInvalid != InvalidFPRReg); + m_jit->unlock(m_fprOrInvalid); + } + + NodeIndex index() const + { + return m_index; + } + + FPRReg fpr() + { + if (m_fprOrInvalid == InvalidFPRReg) + m_fprOrInvalid = m_jit->fillDouble(index()); + return m_fprOrInvalid; + } + + MacroAssembler::FPRegisterID registerID() + { + return JITCompiler::fprToRegisterID(fpr()); + } + +private: + JITCodeGenerator* m_jit; + NodeIndex m_index; + FPRReg m_fprOrInvalid; +}; + +class JSValueOperand { +public: + explicit JSValueOperand(JITCodeGenerator* jit, NodeIndex index) + : m_jit(jit) + , m_index(index) + , m_gprOrInvalid(InvalidGPRReg) + { + ASSERT(m_jit); + if (jit->isFilled(index)) + gpr(); + } + + ~JSValueOperand() + { + ASSERT(m_gprOrInvalid != InvalidGPRReg); + m_jit->unlock(m_gprOrInvalid); + } + + NodeIndex index() const + { + return m_index; + } + + GPRReg gpr() + { + if (m_gprOrInvalid == InvalidGPRReg) + m_gprOrInvalid = m_jit->fillJSValue(index()); + return m_gprOrInvalid; + } + + MacroAssembler::RegisterID registerID() + { + return JITCompiler::gprToRegisterID(gpr()); + } + +private: + JITCodeGenerator* m_jit; + NodeIndex m_index; + GPRReg m_gprOrInvalid; +}; + + +// === Temporaries === +// +// These classes are used to allocate temporary registers. +// A mechanism is provided to attempt to reuse the registers +// currently allocated to child nodes whose value is consumed +// by, and not live after, this operation. + +class GPRTemporary { +public: + GPRTemporary(JITCodeGenerator*); + GPRTemporary(JITCodeGenerator*, SpeculateIntegerOperand&); + GPRTemporary(JITCodeGenerator*, SpeculateIntegerOperand&, SpeculateIntegerOperand&); + GPRTemporary(JITCodeGenerator*, IntegerOperand&); + GPRTemporary(JITCodeGenerator*, IntegerOperand&, IntegerOperand&); + GPRTemporary(JITCodeGenerator*, SpeculateCellOperand&); + GPRTemporary(JITCodeGenerator*, JSValueOperand&); + + ~GPRTemporary() + { + m_jit->unlock(gpr()); + } + + GPRReg gpr() const + { + ASSERT(m_gpr != InvalidGPRReg); + return m_gpr; + } + + MacroAssembler::RegisterID registerID() + { + ASSERT(m_gpr != InvalidGPRReg); + return JITCompiler::gprToRegisterID(m_gpr); + } + +protected: + GPRTemporary(JITCodeGenerator* jit, GPRReg lockedGPR) + : m_jit(jit) + , m_gpr(lockedGPR) + { + } + +private: + JITCodeGenerator* m_jit; + GPRReg m_gpr; +}; + +class FPRTemporary { +public: + FPRTemporary(JITCodeGenerator*); + FPRTemporary(JITCodeGenerator*, DoubleOperand&); + FPRTemporary(JITCodeGenerator*, DoubleOperand&, DoubleOperand&); + + ~FPRTemporary() + { + m_jit->unlock(fpr()); + } + + FPRReg fpr() const + { + ASSERT(m_fpr != InvalidFPRReg); + return m_fpr; + } + + MacroAssembler::FPRegisterID registerID() + { + ASSERT(m_fpr != InvalidFPRReg); + return JITCompiler::fprToRegisterID(m_fpr); + } + +protected: + FPRTemporary(JITCodeGenerator* jit, FPRReg lockedFPR) + : m_jit(jit) + , m_fpr(lockedFPR) + { + } + +private: + JITCodeGenerator* m_jit; + FPRReg m_fpr; +}; + + +// === Results === +// +// These classes lock the result of a call to a C++ helper function. + +class GPRResult : public GPRTemporary { +public: + GPRResult(JITCodeGenerator* jit) + : GPRTemporary(jit, lockedResult(jit)) + { + } + +private: + static GPRReg lockedResult(JITCodeGenerator* jit) + { + jit->lock(JITCompiler::returnValueGPR); + return JITCompiler::returnValueGPR; + } +}; + +class FPRResult : public FPRTemporary { +public: + FPRResult(JITCodeGenerator* jit) + : FPRTemporary(jit, lockedResult(jit)) + { + } + +private: + static FPRReg lockedResult(JITCodeGenerator* jit) + { + jit->lock(JITCompiler::returnValueFPR); + return JITCompiler::returnValueFPR; + } +}; + +} } // namespace JSC::DFG + +#endif +#endif + diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp new file mode 100644 index 0000000..5c5d5fe --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp @@ -0,0 +1,429 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DFGJITCompiler.h" + +#if ENABLE(DFG_JIT) + +#include "CodeBlock.h" +#include "DFGJITCodeGenerator.h" +#include "DFGNonSpeculativeJIT.h" +#include "DFGOperations.h" +#include "DFGRegisterBank.h" +#include "DFGSpeculativeJIT.h" +#include "JSGlobalData.h" +#include "LinkBuffer.h" + +namespace JSC { namespace DFG { + +// This method used to fill a numeric value to a FPR when linking speculative -> non-speculative. +void JITCompiler::fillNumericToDouble(NodeIndex nodeIndex, FPRReg fpr, GPRReg temporary) +{ + Node& node = graph()[nodeIndex]; + MacroAssembler::RegisterID tempReg = gprToRegisterID(temporary); + + // Arguments can't be know to be double, would need to have been a ValueToNumber node in the way! + ASSERT(!node.isArgument()); + + if (node.isConstant()) { + ASSERT(node.op == DoubleConstant); + move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfDoubleConstant(nodeIndex)))), tempReg); + movePtrToDouble(tempReg, fprToRegisterID(fpr)); + } else { + loadPtr(addressFor(node.virtualRegister), tempReg); + Jump isInteger = branchPtr(MacroAssembler::AboveOrEqual, tempReg, tagTypeNumberRegister); + jitAssertIsJSDouble(gpr0); + addPtr(tagTypeNumberRegister, tempReg); + movePtrToDouble(tempReg, fprToRegisterID(fpr)); + Jump hasUnboxedDouble = jump(); + isInteger.link(this); + convertInt32ToDouble(tempReg, fprToRegisterID(fpr)); + hasUnboxedDouble.link(this); + } +} + +// This method used to fill an integer value to a GPR when linking speculative -> non-speculative. +void JITCompiler::fillInt32ToInteger(NodeIndex nodeIndex, GPRReg gpr) +{ + Node& node = graph()[nodeIndex]; + + // Arguments can't be know to be int32, would need to have been a ValueToInt32 node in the way! + ASSERT(!node.isArgument()); + + if (node.isConstant()) { + ASSERT(node.op == Int32Constant); + move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gprToRegisterID(gpr)); + } else { +#if DFG_JIT_ASSERT + // Redundant load, just so we can check the tag! + loadPtr(addressFor(node.virtualRegister), gprToRegisterID(gpr)); + jitAssertIsJSInt32(gpr); +#endif + load32(addressFor(node.virtualRegister), gprToRegisterID(gpr)); + } +} + +// This method used to fill a JSValue to a GPR when linking speculative -> non-speculative. +void JITCompiler::fillToJS(NodeIndex nodeIndex, GPRReg gpr) +{ + Node& node = graph()[nodeIndex]; + + if (node.isArgument()) { + loadPtr(addressForArgument(node.argumentNumber()), gprToRegisterID(gpr)); + return; + } + + if (node.isConstant()) { + if (isInt32Constant(nodeIndex)) { + JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex)); + move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gprToRegisterID(gpr)); + } else if (isDoubleConstant(nodeIndex)) { + JSValue jsValue(JSValue::EncodeAsDouble, valueOfDoubleConstant(nodeIndex)); + move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gprToRegisterID(gpr)); + } else { + ASSERT(isJSConstant(nodeIndex)); + JSValue jsValue = valueOfJSConstant(nodeIndex); + move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gprToRegisterID(gpr)); + } + return; + } + + loadPtr(addressFor(node.virtualRegister), gprToRegisterID(gpr)); +} + +void JITCompiler::jumpFromSpeculativeToNonSpeculative(const SpeculationCheck& check, const EntryLocation& entry, SpeculationRecovery* recovery) +{ + ASSERT(check.m_nodeIndex == entry.m_nodeIndex); + + // Link the jump from the Speculative path to here. + check.m_check.link(this); + + // Does this speculation check require any additional recovery to be performed, + // to restore any state that has been overwritten before we enter back in to the + // non-speculative path. + if (recovery) { + // The only additional recovery we currently support is for integer add operation + ASSERT(recovery->type() == SpeculativeAdd); + // Revert the add. + sub32(gprToRegisterID(recovery->src()), gprToRegisterID(recovery->dest())); + } + + // FIXME: - This is hideously inefficient! + // Where a value is live in a register in the speculative path, and is required in a register + // on the non-speculative path, we should not need to be spilling it and reloading (we may + // need to spill anyway, if the value is marked as spilled on the non-speculative path). + // This may also be spilling values that don't need spilling, e.g. are already spilled, + // are constants, or are arguments. + + // Spill all GPRs in use by the speculative path. + for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) { + NodeIndex nodeIndex = check.m_gprInfo[gpr].nodeIndex; + if (nodeIndex == NoNode) + continue; + + DataFormat dataFormat = check.m_gprInfo[gpr].format; + VirtualRegister virtualRegister = graph()[nodeIndex].virtualRegister; + + ASSERT(dataFormat == DataFormatInteger || DataFormatCell || dataFormat & DataFormatJS); + if (dataFormat == DataFormatInteger) + orPtr(tagTypeNumberRegister, gprToRegisterID(gpr)); + storePtr(gprToRegisterID(gpr), addressFor(virtualRegister)); + } + + // Spill all FPRs in use by the speculative path. + for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) { + NodeIndex nodeIndex = check.m_fprInfo[fpr]; + if (nodeIndex == NoNode) + continue; + + VirtualRegister virtualRegister = graph()[nodeIndex].virtualRegister; + + moveDoubleToPtr(fprToRegisterID(fpr), regT0); + subPtr(tagTypeNumberRegister, regT0); + storePtr(regT0, addressFor(virtualRegister)); + } + + // Fill all FPRs in use by the non-speculative path. + for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) { + NodeIndex nodeIndex = entry.m_fprInfo[fpr]; + if (nodeIndex == NoNode) + continue; + + fillNumericToDouble(nodeIndex, fpr, gpr0); + } + + // Fill all GPRs in use by the non-speculative path. + for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) { + NodeIndex nodeIndex = entry.m_gprInfo[gpr].nodeIndex; + if (nodeIndex == NoNode) + continue; + + DataFormat dataFormat = entry.m_gprInfo[gpr].format; + if (dataFormat == DataFormatInteger) + fillInt32ToInteger(nodeIndex, gpr); + else { + ASSERT(dataFormat & DataFormatJS || dataFormat == DataFormatCell); // Treat cell as JSValue for now! + fillToJS(nodeIndex, gpr); + // FIXME: For subtypes of DataFormatJS, should jitAssert the subtype? + } + } + + // Jump into the non-speculative path. + jump(entry.m_entry); +} + +void JITCompiler::linkSpeculationChecks(SpeculativeJIT& speculative, NonSpeculativeJIT& nonSpeculative) +{ + // Iterators to walk over the set of bail outs & corresponding entry points. + SpeculativeJIT::SpeculationCheckVector::Iterator checksIter = speculative.speculationChecks().begin(); + SpeculativeJIT::SpeculationCheckVector::Iterator checksEnd = speculative.speculationChecks().end(); + NonSpeculativeJIT::EntryLocationVector::Iterator entriesIter = nonSpeculative.entryLocations().begin(); + NonSpeculativeJIT::EntryLocationVector::Iterator entriesEnd = nonSpeculative.entryLocations().end(); + + // Iterate over the speculation checks. + while (checksIter != checksEnd) { + // For every bail out from the speculative path, we must have provided an entry point + // into the non-speculative one. + ASSERT(checksIter->m_nodeIndex == entriesIter->m_nodeIndex); + + // There may be multiple bail outs that map to the same entry point! + do { + ASSERT(checksIter != checksEnd); + ASSERT(entriesIter != entriesEnd); + + // Plant code to link this speculation failure. + const SpeculationCheck& check = *checksIter; + const EntryLocation& entry = *entriesIter; + jumpFromSpeculativeToNonSpeculative(check, entry, speculative.speculationRecovery(check.m_recoveryIndex)); + ++checksIter; + } while (checksIter != checksEnd && checksIter->m_nodeIndex == entriesIter->m_nodeIndex); + ++entriesIter; + } + + // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56289 + ASSERT(!(checksIter != checksEnd)); + ASSERT(!(entriesIter != entriesEnd)); +} + +void JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck) +{ + // === Stage 1 - Function header code generation === + // + // This code currently matches the old JIT. In the function header we need to + // pop the return address (since we do not allow any recursion on the machine + // stack), and perform a fast register file check. + + // This is the main entry point, without performing an arity check. + // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56292 + // We'll need to convert the remaining cti_ style calls (specifically the register file + // check) which will be dependent on stack layout. (We'd need to account for this in + // both normal return code and when jumping to an exception handler). + preserveReturnAddressAfterCall(regT2); + emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC); + // If we needed to perform an arity check we will already have moved the return address, + // so enter after this. + Label fromArityCheck(this); + + // Setup a pointer to the codeblock in the CallFrameHeader. + emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock); + + // Plant a check that sufficient space is available in the RegisterFile. + // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56291 + addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), callFrameRegister, regT1); + Jump registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT1); + // Return here after register file check. + Label fromRegisterFileCheck = label(); + + + // === Stage 2 - Function body code generation === + // + // We generate the speculative code path, followed by the non-speculative + // code for the function. Next we need to link the two together, making + // bail-outs from the speculative path jump to the corresponding point on + // the non-speculative one (and generating any code necessary to juggle + // register values around, rebox values, and ensure spilled, to match the + // non-speculative path's requirements). + +#if DFG_JIT_BREAK_ON_ENTRY + // Handy debug tool! + breakpoint(); +#endif + + // First generate the speculative path. + SpeculativeJIT speculative(*this); + speculative.compile(); + + // Next, generate the non-speculative path. We pass this a SpeculationCheckIndexIterator + // to allow it to check which nodes in the graph may bail out, and may need to reenter the + // non-speculative path. + SpeculationCheckIndexIterator checkIterator(speculative); + NonSpeculativeJIT nonSpeculative(*this); + nonSpeculative.compile(checkIterator); + + // Link the bail-outs from the speculative path to the corresponding entry points into the non-speculative one. + linkSpeculationChecks(speculative, nonSpeculative); + + + // === Stage 3 - Function footer code generation === + // + // Generate code to lookup and jump to exception handlers, to perform the slow + // register file check (if the fast one in the function header fails), and + // generate the entry point with arity check. + + // Iterate over the m_calls vector, checking for exception checks, + // and linking them to here. + unsigned exceptionCheckCount = 0; + for (unsigned i = 0; i < m_calls.size(); ++i) { + Jump& exceptionCheck = m_calls[i].m_exceptionCheck; + if (exceptionCheck.isSet()) { + exceptionCheck.link(this); + ++exceptionCheckCount; + } + } + // If any exception checks were linked, generate code to lookup a handler. + if (exceptionCheckCount) { + // lookupExceptionHandler is passed two arguments, exec (the CallFrame*), and + // an identifier for the operation that threw the exception, which we can use + // to look up handler information. The identifier we use is the return address + // of the call out from JIT code that threw the exception; this is still + // available on the stack, just below the stack pointer! + move(callFrameRegister, argumentRegister0); + peek(argumentRegister1, -1); + m_calls.append(CallRecord(call(), lookupExceptionHandler)); + // lookupExceptionHandler leaves the handler CallFrame* in the returnValueRegister, + // and the address of the handler in returnValueRegister2. + jump(returnValueRegister2); + } + + // Generate the register file check; if the fast check in the function head fails, + // we need to call out to a helper function to check whether more space is available. + // FIXME: change this from a cti call to a DFG style operation (normal C calling conventions). + registerFileCheck.link(this); + move(stackPointerRegister, argumentRegister0); + poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); + Call callRegisterFileCheck = call(); + jump(fromRegisterFileCheck); + + // The fast entry point into a function does not check the correct number of arguments + // have been passed to the call (we only use the fast entry point where we can statically + // determine the correct number of arguments have been passed, or have already checked). + // In cases where an arity check is necessary, we enter here. + // FIXME: change this from a cti call to a DFG style operation (normal C calling conventions). + Label arityCheck = label(); + preserveReturnAddressAfterCall(regT2); + emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC); + branch32(Equal, regT1, Imm32(m_codeBlock->m_numParameters)).linkTo(fromArityCheck, this); + move(stackPointerRegister, argumentRegister0); + poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); + Call callArityCheck = call(); + move(regT0, callFrameRegister); + jump(fromArityCheck); + + + // === Stage 4 - Link === + // + // Link the code, populate data in CodeBlock data structures. + + LinkBuffer linkBuffer(this, m_globalData->executableAllocator.poolForSize(m_assembler.size()), 0); + + // Link all calls out from the JIT code to their respective functions. + for (unsigned i = 0; i < m_calls.size(); ++i) + linkBuffer.link(m_calls[i].m_call, m_calls[i].m_function); + + if (m_codeBlock->needsCallReturnIndices()) { + m_codeBlock->callReturnIndexVector().reserveCapacity(exceptionCheckCount); + for (unsigned i = 0; i < m_calls.size(); ++i) { + if (m_calls[i].m_exceptionCheck.isSet()) { + unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_calls[i].m_call); + unsigned exceptionInfo = m_calls[i].m_exceptionInfo; + m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo)); + } + } + } + + // FIXME: switch the register file check & arity check over to DFGOpertaion style calls, not JIT stubs. + linkBuffer.link(callRegisterFileCheck, cti_register_file_check); + linkBuffer.link(callArityCheck, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck); + + entryWithArityCheck = linkBuffer.locationOf(arityCheck); + entry = linkBuffer.finalizeCode(); +} + +#if DFG_JIT_ASSERT +void JITCompiler::jitAssertIsInt32(GPRReg gpr) +{ +#if CPU(X86_64) + Jump checkInt32 = branchPtr(BelowOrEqual, gprToRegisterID(gpr), TrustedImmPtr(reinterpret_cast<void*>(static_cast<uintptr_t>(0xFFFFFFFFu)))); + breakpoint(); + checkInt32.link(this); +#else + UNUSED_PARAM(gpr); +#endif +} + +void JITCompiler::jitAssertIsJSInt32(GPRReg gpr) +{ + Jump checkJSInt32 = branchPtr(AboveOrEqual, gprToRegisterID(gpr), tagTypeNumberRegister); + breakpoint(); + checkJSInt32.link(this); +} + +void JITCompiler::jitAssertIsJSNumber(GPRReg gpr) +{ + Jump checkJSNumber = branchTestPtr(MacroAssembler::NonZero, gprToRegisterID(gpr), tagTypeNumberRegister); + breakpoint(); + checkJSNumber.link(this); +} + +void JITCompiler::jitAssertIsJSDouble(GPRReg gpr) +{ + Jump checkJSInt32 = branchPtr(AboveOrEqual, gprToRegisterID(gpr), tagTypeNumberRegister); + Jump checkJSNumber = branchTestPtr(MacroAssembler::NonZero, gprToRegisterID(gpr), tagTypeNumberRegister); + checkJSInt32.link(this); + breakpoint(); + checkJSNumber.link(this); +} +#endif + +#if ENABLE(SAMPLING_COUNTERS) && CPU(X86_64) // Or any other 64-bit platform! +void JITCompiler::emitCount(AbstractSamplingCounter& counter, uint32_t increment) +{ + addPtr(TrustedImm32(increment), AbsoluteAddress(counter.addressOfCounter())); +} +#endif + +#if ENABLE(SAMPLING_COUNTERS) && CPU(X86) // Or any other little-endian 32-bit platform! +void JITCompiler::emitCount(AbstractSamplingCounter& counter, uint32_t increment) +{ + intptr_t hiWord = reinterpret_cast<intptr_t>(counter.addressOfCounter()) + sizeof(int32_t); + add32(TrustedImm32(increment), AbsoluteAddress(counter.addressOfCounter())); + addWithCarry32(TrustedImm32(0), AbsoluteAddress(reinterpret_cast<void*>(hiWord))); +} +#endif + +} } // namespace JSC::DFG + +#endif diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.h b/Source/JavaScriptCore/dfg/DFGJITCompiler.h new file mode 100644 index 0000000..8b68434 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.h @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGJITCompiler_h +#define DFGJITCompiler_h + +#if ENABLE(DFG_JIT) + +#include <assembler/MacroAssembler.h> +#include <bytecode/CodeBlock.h> +#include <dfg/DFGGraph.h> +#include <jit/JITCode.h> + +namespace JSC { + +class AbstractSamplingCounter; +class CodeBlock; +class JSGlobalData; + +namespace DFG { + +class JITCodeGenerator; +class NonSpeculativeJIT; +class SpeculativeJIT; +class SpeculationRecovery; + +struct EntryLocation; +struct SpeculationCheck; + +// Abstracted sequential numbering of available machine registers (as opposed to MacroAssembler::RegisterID, +// which are non-sequential, and not abstracted from the register numbering used by the underlying processor). +enum GPRReg { gpr0, gpr1, gpr2, gpr3, gpr4, gpr5, numberOfGPRs, InvalidGPRReg = 0xFFFFFFFF }; +enum FPRReg { fpr0, fpr1, fpr2, fpr3, fpr4, fpr5, numberOfFPRs, InvalidFPRReg = 0xFFFFFFFF }; + +// GPRReg/FPRReg are enum types to provide type checking at compile time, use these method to iterate. +inline GPRReg next(GPRReg& reg) +{ + ASSERT(reg < numberOfGPRs); + return reg = static_cast<GPRReg>(reg + 1); +} +inline FPRReg next(FPRReg& reg) +{ + ASSERT(reg < numberOfFPRs); + return reg = static_cast<FPRReg>(reg + 1); +} + +// === CallRecord === +// +// A record of a call out from JIT code to a helper function. +// Every CallRecord contains a reference to the call instruction & the function +// that it needs to be linked to. Calls that might throw an exception also record +// the Jump taken on exception (unset if not present), and ExceptionInfo (presently +// an unsigned, bytecode index) used to recover handler/source info. +struct CallRecord { + // Constructor for a call with no exception handler. + CallRecord(MacroAssembler::Call call, FunctionPtr function) + : m_call(call) + , m_function(function) + { + } + + // Constructor for a call with an exception handler. + CallRecord(MacroAssembler::Call call, FunctionPtr function, MacroAssembler::Jump exceptionCheck, ExceptionInfo exceptionInfo) + : m_call(call) + , m_function(function) + , m_exceptionCheck(exceptionCheck) + , m_exceptionInfo(exceptionInfo) + { + } + + MacroAssembler::Call m_call; + FunctionPtr m_function; + MacroAssembler::Jump m_exceptionCheck; + ExceptionInfo m_exceptionInfo; +}; + +// === JITCompiler === +// +// DFG::JITCompiler is responsible for generating JIT code from the dataflow graph. +// It does so by delegating to the speculative & non-speculative JITs, which +// generate to a MacroAssembler (which the JITCompiler owns through an inheritance +// relationship). The JITCompiler holds references to information required during +// compilation, and also records information used in linking (e.g. a list of all +// call to be linked). +class JITCompiler : public MacroAssembler { +public: + JITCompiler(JSGlobalData* globalData, Graph& dfg, CodeBlock* codeBlock) + : m_globalData(globalData) + , m_graph(dfg) + , m_codeBlock(codeBlock) + { + } + + void compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck); + + // Accessors for properties. + Graph& graph() { return m_graph; } + CodeBlock* codeBlock() { return m_codeBlock; } + JSGlobalData* globalData() { return m_globalData; } + +#if CPU(X86_64) + // These registers match the old JIT. + static const RegisterID timeoutCheckRegister = X86Registers::r12; + static const RegisterID callFrameRegister = X86Registers::r13; + static const RegisterID tagTypeNumberRegister = X86Registers::r14; + static const RegisterID tagMaskRegister = X86Registers::r15; + + // Temporary registers (these correspond to the temporary GPRReg/FPRReg + // registers i.e. regT0 and grp0 refer to the same thing, grp0 being + // the abstracted, sequential name, and regT0 being the machine register + // number in the instruction set, as provided by the MacroAssembler). + static const RegisterID regT0 = X86Registers::eax; + static const RegisterID regT1 = X86Registers::edx; + static const RegisterID regT2 = X86Registers::ecx; + static const RegisterID regT3 = X86Registers::ebx; + static const RegisterID regT4 = X86Registers::edi; + static const RegisterID regT5 = X86Registers::esi; + static const FPRegisterID fpRegT0 = X86Registers::xmm0; + static const FPRegisterID fpRegT1 = X86Registers::xmm1; + static const FPRegisterID fpRegT2 = X86Registers::xmm2; + static const FPRegisterID fpRegT3 = X86Registers::xmm3; + static const FPRegisterID fpRegT4 = X86Registers::xmm4; + static const FPRegisterID fpRegT5 = X86Registers::xmm5; + + // These constants provide both RegisterID & GPRReg style names for the + // general purpose argument & return value register. + static const GPRReg argumentGPR0 = gpr4; + static const GPRReg argumentGPR1 = gpr5; + static const GPRReg argumentGPR2 = gpr1; + static const GPRReg argumentGPR3 = gpr2; + static const RegisterID argumentRegister0 = regT4; + static const RegisterID argumentRegister1 = regT5; + static const RegisterID argumentRegister2 = regT1; + static const RegisterID argumentRegister3 = regT2; + static const GPRReg returnValueGPR = gpr0; + static const RegisterID returnValueRegister = regT0; + static const RegisterID returnValueRegister2 = regT1; + + // These constants provide both FPRegisterID & FPRReg style names for the + // floating point argument & return value register. + static const FPRReg argumentFPR0 = fpr0; + static const FPRReg argumentFPR1 = fpr1; + static const FPRReg argumentFPR2 = fpr2; + static const FPRReg argumentFPR3 = fpr3; + static const FPRegisterID fpArgumentRegister0 = fpRegT0; + static const FPRegisterID fpArgumentRegister1 = fpRegT1; + static const FPRegisterID fpArgumentRegister2 = fpRegT2; + static const FPRegisterID fpArgumentRegister3 = fpRegT3; + static const FPRReg returnValueFPR = fpr0; + static const FPRegisterID fpReturnValueRegister = fpRegT0; + + + void preserveReturnAddressAfterCall(RegisterID reg) + { + pop(reg); + } + + void restoreReturnAddressBeforeReturn(RegisterID reg) + { + push(reg); + } + + void restoreReturnAddressBeforeReturn(Address address) + { + push(address); + } + + void emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, RegisterID to) + { + loadPtr(Address(callFrameRegister, entry * sizeof(Register)), to); + } + void emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry) + { + storePtr(from, Address(callFrameRegister, entry * sizeof(Register))); + } + + void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry) + { + storePtr(TrustedImmPtr(value), Address(callFrameRegister, entry * sizeof(Register))); + } +#endif + + Address addressForArgument(int32_t argument) + { + return Address(callFrameRegister, (argument - (m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize)) * sizeof(Register)); + } + + static Address addressForGlobalVar(RegisterID global, int32_t varNumber) + { + return Address(global, varNumber * sizeof(Register)); + } + + static Address addressFor(VirtualRegister virtualRegister) + { + return Address(callFrameRegister, virtualRegister * sizeof(Register)); + } + + // These methods provide mapping from sequential register numbering (GPRReg/FPRReg) + // to machine register numbering (RegisterID/FPRegisterID). + static RegisterID gprToRegisterID(GPRReg reg) + { + ASSERT(reg < numberOfGPRs); + static const RegisterID idForRegister[numberOfGPRs] = { regT0, regT1, regT2, regT3, regT4, regT5 }; + return idForRegister[reg]; + } + static FPRegisterID fprToRegisterID(FPRReg reg) + { + ASSERT(reg < numberOfFPRs); + static const FPRegisterID idForRegister[numberOfFPRs] = { fpRegT0, fpRegT1, fpRegT2, fpRegT3, fpRegT4, fpRegT5 }; + return idForRegister[reg]; + } + + // Add a call out from JIT code, without an exception check. + void appendCall(const FunctionPtr& function) + { + m_calls.append(CallRecord(call(), function)); + // FIXME: should be able to JIT_ASSERT here that globalData->exception is null on return back to JIT code. + } + + // Add a call out from JIT code, with an exception check. + void appendCallWithExceptionCheck(const FunctionPtr& function, unsigned exceptionInfo) + { + Call functionCall = call(); + Jump exceptionCheck = branchTestPtr(NonZero, AbsoluteAddress(&globalData()->exception)); + m_calls.append(CallRecord(functionCall, function, exceptionCheck, exceptionInfo)); + } + + // Helper methods to check nodes for constants. + bool isInt32Constant(NodeIndex nodeIndex) + { + return graph()[nodeIndex].op == Int32Constant; + } + bool isDoubleConstant(NodeIndex nodeIndex) + { + return graph()[nodeIndex].op == DoubleConstant; + } + bool isJSConstant(NodeIndex nodeIndex) + { + return graph()[nodeIndex].op == JSConstant; + } + + // Helper methods get constant values from nodes. + int32_t valueOfInt32Constant(NodeIndex nodeIndex) + { + ASSERT(isInt32Constant(nodeIndex)); + return graph()[nodeIndex].int32Constant(); + } + double valueOfDoubleConstant(NodeIndex nodeIndex) + { + ASSERT(isDoubleConstant(nodeIndex)); + return graph()[nodeIndex].numericConstant(); + } + JSValue valueOfJSConstant(NodeIndex nodeIndex) + { + ASSERT(isJSConstant(nodeIndex)); + unsigned constantIndex = graph()[nodeIndex].constantNumber(); + return codeBlock()->constantRegister(FirstConstantRegisterIndex + constantIndex).get(); + } + + // These methods JIT generate dynamic, debug-only checks - akin to ASSERTs. +#if DFG_JIT_ASSERT + void jitAssertIsInt32(GPRReg); + void jitAssertIsJSInt32(GPRReg); + void jitAssertIsJSNumber(GPRReg); + void jitAssertIsJSDouble(GPRReg); +#else + void jitAssertIsInt32(GPRReg) {} + void jitAssertIsJSInt32(GPRReg) {} + void jitAssertIsJSNumber(GPRReg) {} + void jitAssertIsJSDouble(GPRReg) {} +#endif + +#if ENABLE(SAMPLING_COUNTERS) + // Debug profiling tool. + void emitCount(AbstractSamplingCounter&, uint32_t increment = 1); +#endif + +private: + // These methods used in linking the speculative & non-speculative paths together. + void fillNumericToDouble(NodeIndex, FPRReg, GPRReg temporary); + void fillInt32ToInteger(NodeIndex, GPRReg); + void fillToJS(NodeIndex, GPRReg); + void jumpFromSpeculativeToNonSpeculative(const SpeculationCheck&, const EntryLocation&, SpeculationRecovery*); + void linkSpeculationChecks(SpeculativeJIT&, NonSpeculativeJIT&); + + // The globalData, used to access constants such as the vPtrs. + JSGlobalData* m_globalData; + + // The dataflow graph currently being generated. + Graph& m_graph; + + // The codeBlock currently being generated, used to access information such as constant values, immediates. + CodeBlock* m_codeBlock; + + // Vector of calls out from JIT code, including exception handler information. + Vector<CallRecord> m_calls; +}; + +} } // namespace JSC::DFG + +#endif +#endif + diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h new file mode 100644 index 0000000..11dbf0d --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGNode.h @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGNode_h +#define DFGNode_h + +#if ENABLE(DFG_JIT) + +#include <wtf/Vector.h> + +// Emit various logging information for debugging, including dumping the dataflow graphs. +#define DFG_DEBUG_VERBOSE 0 +// Enable generation of dynamic checks into the instruction stream. +#define DFG_JIT_ASSERT 0 +// Consistency check contents compiler data structures. +#define DFG_CONSISTENCY_CHECK 0 +// Emit a breakpoint into the head of every generated function, to aid debugging in GDB. +#define DFG_JIT_BREAK_ON_ENTRY 0 + + +namespace JSC { namespace DFG { + +// Type for a virtual register number (spill location). +// Using an enum to make this type-checked at compile time, to avert programmer errors. +enum VirtualRegister { InvalidVirtualRegister = -1 }; +COMPILE_ASSERT(sizeof(VirtualRegister) == sizeof(int), VirtualRegister_is_32bit); + +// Type for a reference to another node in the graph. +typedef uint32_t NodeIndex; +static const NodeIndex NoNode = UINT_MAX; + +// Information used to map back from an exception to any handler/source information. +// (Presently implemented as a bytecode index). +typedef uint32_t ExceptionInfo; + +// Entries in the NodeType enum (below) are composed of an id, a result type (possibly none) +// and some additional informative flags (must generate, is constant, etc). +#define NodeIdMask 0xFFF +#define NodeResultMask 0xF000 +#define NodeMustGenerate 0x10000 // set on nodes that have side effects, and may not trivially be removed by DCE. +#define NodeIsConstant 0x20000 + +// These values record the result type of the node (as checked by NodeResultMask, above), 0 for no result. +#define NodeResultJS 0x1000 +#define NodeResultDouble 0x2000 +#define NodeResultInt32 0x3000 + +// This macro defines a set of information about all known node types, used to populate NodeId, NodeType below. +#define FOR_EACH_DFG_OP(macro) \ + /* Nodes for constants. */\ + macro(JSConstant, NodeResultJS | NodeIsConstant) \ + macro(Int32Constant, NodeResultJS | NodeIsConstant) \ + macro(DoubleConstant, NodeResultJS | NodeIsConstant) \ + macro(Argument, NodeResultJS) \ + macro(ConvertThis, NodeResultJS) \ + \ + /* Nodes for bitwise operations. */\ + macro(BitAnd, NodeResultInt32) \ + macro(BitOr, NodeResultInt32) \ + macro(BitXor, NodeResultInt32) \ + macro(BitLShift, NodeResultInt32) \ + macro(BitRShift, NodeResultInt32) \ + macro(BitURShift, NodeResultInt32) \ + /* Bitwise operators call ToInt32 on their operands. */\ + macro(NumberToInt32, NodeResultInt32) \ + macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \ + /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\ + macro(UInt32ToNumber, NodeResultDouble) \ + \ + /* Nodes for arithmetic operations. */\ + macro(ArithAdd, NodeResultDouble) \ + macro(ArithSub, NodeResultDouble) \ + macro(ArithMul, NodeResultDouble) \ + macro(ArithDiv, NodeResultDouble) \ + macro(ArithMod, NodeResultDouble) \ + /* Arithmetic operators call ToNumber on their operands. */\ + macro(Int32ToNumber, NodeResultDouble) \ + macro(ValueToNumber, NodeResultDouble | NodeMustGenerate) \ + \ + /* Add of values may either be arithmetic, or result in string concatenation. */\ + macro(ValueAdd, NodeResultJS | NodeMustGenerate) \ + \ + /* Property access. */\ + /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\ + /* Since a put to 'length' may invalidate optimizations here, */\ + /* this must be the directly subsequent property put. */\ + macro(GetByVal, NodeResultJS | NodeMustGenerate) \ + macro(PutByVal, NodeMustGenerate) \ + macro(PutByValAlias, NodeMustGenerate) \ + macro(GetById, NodeResultJS | NodeMustGenerate) \ + macro(PutById, NodeMustGenerate) \ + macro(PutByIdDirect, NodeMustGenerate) \ + macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \ + macro(PutGlobalVar, NodeMustGenerate) \ + \ + macro(Return, NodeMustGenerate) + +// This enum generates a monotonically increasing id for all Node types, +// and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask). +enum NodeId { +#define DFG_OP_ENUM(opcode, flags) opcode##_id, + FOR_EACH_DFG_OP(DFG_OP_ENUM) +#undef DFG_OP_ENUM +}; + +// Entries in this enum describe all Node types. +// The enum value contains a monotonically increasing id, a result type, and additional flags. +enum NodeType { +#define DFG_OP_ENUM(opcode, flags) opcode = opcode##_id | (flags), + FOR_EACH_DFG_OP(DFG_OP_ENUM) +#undef DFG_OP_ENUM +}; + +// This type used in passing an immediate argument to Node constructor; +// distinguishes an immediate value (typically an index into a CodeBlock data structure - +// a constant index, argument, or identifier) from a NodeIndex. +struct OpInfo { + explicit OpInfo(unsigned value) : m_value(value) {} + unsigned m_value; +}; + +// === Node === +// +// Node represents a single operation in the data flow graph. +struct Node { + // Construct a node with up to 3 children, no immediate value. + Node(NodeType op, ExceptionInfo exceptionInfo, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) + : op(op) + , exceptionInfo(exceptionInfo) + , child1(child1) + , child2(child2) + , child3(child3) + , virtualRegister(InvalidVirtualRegister) + , refCount(0) + { + } + + // Construct a node with up to 3 children and an immediate value. + Node(NodeType op, ExceptionInfo exceptionInfo, OpInfo imm, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) + : op(op) + , exceptionInfo(exceptionInfo) + , child1(child1) + , child2(child2) + , child3(child3) + , virtualRegister(InvalidVirtualRegister) + , refCount(0) + , m_opInfo(imm.m_value) + { + } + + bool mustGenerate() + { + return op & NodeMustGenerate; + } + + bool isConstant() + { + return op & NodeIsConstant; + } + + unsigned constantNumber() + { + ASSERT(isConstant()); + return m_opInfo; + } + + bool isArgument() + { + return op == Argument; + } + + unsigned argumentNumber() + { + ASSERT(isArgument()); + return m_opInfo; + } + + bool hasIdentifier() + { + return op == GetById || op == PutById || op == PutByIdDirect; + } + + unsigned identifierNumber() + { + ASSERT(hasIdentifier()); + return m_opInfo; + } + + bool hasVarNumber() + { + return op == GetGlobalVar || op == PutGlobalVar; + } + + unsigned varNumber() + { + ASSERT(hasVarNumber()); + return m_opInfo; + } + + bool hasInt32Result() + { + return (op & NodeResultMask) == NodeResultInt32; + } + + bool hasDoubleResult() + { + return (op & NodeResultMask) == NodeResultDouble; + } + + bool hasJSResult() + { + return (op & NodeResultMask) == NodeResultJS; + } + + // Check for integers or doubles. + bool hasNumericResult() + { + // This check will need updating if more result types are added. + ASSERT((hasInt32Result() || hasDoubleResult()) == !hasJSResult()); + return !hasJSResult(); + } + + int32_t int32Constant() + { + ASSERT(op == Int32Constant); + return m_constantValue.asInt32; + } + + void setInt32Constant(int32_t value) + { + ASSERT(op == Int32Constant); + m_constantValue.asInt32 = value; + } + + double numericConstant() + { + ASSERT(op == DoubleConstant); + return m_constantValue.asDouble; + } + + void setDoubleConstant(double value) + { + ASSERT(op == DoubleConstant); + m_constantValue.asDouble = value; + } + + // This enum value describes the type of the node. + NodeType op; + // Used to look up exception handling information (currently implemented as a bytecode index). + ExceptionInfo exceptionInfo; + // References to up to 3 children (0 for no child). + NodeIndex child1, child2, child3; + // The virtual register number (spill location) associated with this . + VirtualRegister virtualRegister; + // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects). + unsigned refCount; + +private: + // An immediate value, accesses type-checked via accessors above. + unsigned m_opInfo; + // The value of an int32/double constant. + union { + int32_t asInt32; + double asDouble; + } m_constantValue; +}; + +} } // namespace JSC::DFG + +#endif +#endif diff --git a/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp new file mode 100644 index 0000000..945c98a --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp @@ -0,0 +1,585 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DFGNonSpeculativeJIT.h" + +#include "DFGSpeculativeJIT.h" + +#if ENABLE(DFG_JIT) + +namespace JSC { namespace DFG { + +const double twoToThe32 = (double)0x100000000ull; + +EntryLocation::EntryLocation(MacroAssembler::Label entry, NonSpeculativeJIT* jit) + : m_entry(entry) + , m_nodeIndex(jit->m_compileIndex) +{ + for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) { + VirtualRegister virtualRegister = jit->m_gprs.name(gpr); + if (virtualRegister != InvalidVirtualRegister) { + GenerationInfo& info = jit->m_generationInfo[virtualRegister]; + m_gprInfo[gpr].nodeIndex = info.nodeIndex(); + m_gprInfo[gpr].format = info.registerFormat(); + } else + m_gprInfo[gpr].nodeIndex = NoNode; + } + for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) { + VirtualRegister virtualRegister = jit->m_fprs.name(fpr); + if (virtualRegister != InvalidVirtualRegister) { + GenerationInfo& info = jit->m_generationInfo[virtualRegister]; + ASSERT(info.registerFormat() == DataFormatDouble); + m_fprInfo[fpr] = info.nodeIndex(); + } else + m_fprInfo[fpr] = NoNode; + } +} + +void NonSpeculativeJIT::valueToNumber(JSValueOperand& operand, FPRReg fpr) +{ + GPRReg jsValueGpr = operand.gpr(); + GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register? + + JITCompiler::RegisterID jsValueReg = JITCompiler::gprToRegisterID(jsValueGpr); + JITCompiler::FPRegisterID fpReg = JITCompiler::fprToRegisterID(fpr); + JITCompiler::RegisterID tempReg = JITCompiler::gprToRegisterID(tempGpr); + + JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueReg, JITCompiler::tagTypeNumberRegister); + JITCompiler::Jump nonNumeric = m_jit.branchTestPtr(MacroAssembler::Zero, jsValueReg, JITCompiler::tagTypeNumberRegister); + + // First, if we get here we have a double encoded as a JSValue + m_jit.move(jsValueReg, tempReg); + m_jit.addPtr(JITCompiler::tagTypeNumberRegister, tempReg); + m_jit.movePtrToDouble(tempReg, fpReg); + JITCompiler::Jump hasUnboxedDouble = m_jit.jump(); + + // Next handle cells (& other JS immediates) + nonNumeric.link(&m_jit); + silentSpillAllRegisters(jsValueGpr); + m_jit.move(jsValueReg, JITCompiler::argumentRegister1); + m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0); + appendCallWithExceptionCheck(dfgConvertJSValueToNumber); + m_jit.moveDouble(JITCompiler::fpReturnValueRegister, fpReg); + silentFillAllRegisters(fpr); + JITCompiler::Jump hasCalledToNumber = m_jit.jump(); + + // Finally, handle integers. + isInteger.link(&m_jit); + m_jit.convertInt32ToDouble(jsValueReg, fpReg); + hasUnboxedDouble.link(&m_jit); + hasCalledToNumber.link(&m_jit); + + m_gprs.unlock(tempGpr); +} + +void NonSpeculativeJIT::valueToInt32(JSValueOperand& operand, GPRReg result) +{ + GPRReg jsValueGpr = operand.gpr(); + + JITCompiler::RegisterID jsValueReg = JITCompiler::gprToRegisterID(jsValueGpr); + JITCompiler::RegisterID resultReg = JITCompiler::gprToRegisterID(result); + + JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueReg, JITCompiler::tagTypeNumberRegister); + + // First handle non-integers + silentSpillAllRegisters(jsValueGpr); + m_jit.move(jsValueReg, JITCompiler::argumentRegister1); + m_jit.move(JITCompiler::callFrameRegister, JITCompiler::argumentRegister0); + appendCallWithExceptionCheck(dfgConvertJSValueToInt32); + m_jit.zeroExtend32ToPtr(JITCompiler::returnValueRegister, resultReg); + silentFillAllRegisters(result); + JITCompiler::Jump hasCalledToInt32 = m_jit.jump(); + + // Then handle integers. + isInteger.link(&m_jit); + m_jit.zeroExtend32ToPtr(jsValueReg, resultReg); + hasCalledToInt32.link(&m_jit); +} + +void NonSpeculativeJIT::numberToInt32(FPRReg fpr, GPRReg gpr) +{ + JITCompiler::FPRegisterID fpReg = JITCompiler::fprToRegisterID(fpr); + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); + + JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpReg, reg, JITCompiler::BranchIfTruncateSuccessful); + + silentSpillAllRegisters(gpr); // don't really care! + + m_jit.moveDouble(fpReg, JITCompiler::fpArgumentRegister0); + appendCallWithExceptionCheck(toInt32); + m_jit.zeroExtend32ToPtr(JITCompiler::returnValueRegister, reg); + + silentFillAllRegisters(gpr); + + truncatedToInteger.link(&m_jit); +} + +void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, Node& node) +{ + // ... + if (checkIterator.hasCheckAtIndex(m_compileIndex)) + trackEntry(m_jit.label()); + + checkConsistency(); + + NodeType op = node.op; + + switch (op) { + case ConvertThis: { + JSValueOperand thisValue(this, node.child1); + GPRReg thisGPR = thisValue.gpr(); + flushRegisters(); + + GPRResult result(this); + callOperation(operationConvertThis, result.gpr(), thisGPR); + cellResult(result.gpr(), m_compileIndex); + break; + } + + case Int32Constant: + case DoubleConstant: + case JSConstant: + initConstantInfo(m_compileIndex); + break; + + case Argument: + initArgumentInfo(m_compileIndex); + break; + + case BitAnd: + case BitOr: + case BitXor: + if (isInt32Constant(node.child1)) { + IntegerOperand op2(this, node.child2); + GPRTemporary result(this, op2); + + bitOp(op, valueOfInt32Constant(node.child1), op2.registerID(), result.registerID()); + + integerResult(result.gpr(), m_compileIndex); + } else if (isInt32Constant(node.child2)) { + IntegerOperand op1(this, node.child1); + GPRTemporary result(this, op1); + + bitOp(op, valueOfInt32Constant(node.child2), op1.registerID(), result.registerID()); + + integerResult(result.gpr(), m_compileIndex); + } else { + IntegerOperand op1(this, node.child1); + IntegerOperand op2(this, node.child2); + GPRTemporary result(this, op1, op2); + + MacroAssembler::RegisterID reg1 = op1.registerID(); + MacroAssembler::RegisterID reg2 = op2.registerID(); + bitOp(op, reg1, reg2, result.registerID()); + + integerResult(result.gpr(), m_compileIndex); + } + break; + + case BitRShift: + case BitLShift: + case BitURShift: + if (isInt32Constant(node.child2)) { + IntegerOperand op1(this, node.child1); + GPRTemporary result(this, op1); + + int shiftAmount = valueOfInt32Constant(node.child2) & 0x1f; + // Shifts by zero should have been optimized out of the graph! + ASSERT(shiftAmount); + shiftOp(op, op1.registerID(), shiftAmount, result.registerID()); + + integerResult(result.gpr(), m_compileIndex); + } else { + // Do not allow shift amount to be used as the result, MacroAssembler does not permit this. + IntegerOperand op1(this, node.child1); + IntegerOperand op2(this, node.child2); + GPRTemporary result(this, op1); + + MacroAssembler::RegisterID reg1 = op1.registerID(); + MacroAssembler::RegisterID reg2 = op2.registerID(); + shiftOp(op, reg1, reg2, result.registerID()); + + integerResult(result.gpr(), m_compileIndex); + } + break; + + case UInt32ToNumber: { + IntegerOperand op1(this, node.child1); + FPRTemporary result(this); + m_jit.convertInt32ToDouble(op1.registerID(), result.registerID()); + + MacroAssembler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.registerID(), TrustedImm32(0)); + m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), result.registerID()); + positive.link(&m_jit); + + doubleResult(result.fpr(), m_compileIndex); + break; + } + + case Int32ToNumber: { + IntegerOperand op1(this, node.child1); + FPRTemporary result(this); + m_jit.convertInt32ToDouble(op1.registerID(), result.registerID()); + doubleResult(result.fpr(), m_compileIndex); + break; + } + + case NumberToInt32: + case ValueToInt32: { + ASSERT(!isInt32Constant(node.child1)); + GenerationInfo& operandInfo = m_generationInfo[m_jit.graph()[node.child1].virtualRegister]; + + switch (operandInfo.registerFormat()) { + case DataFormatInteger: { + IntegerOperand op1(this, node.child1); + GPRTemporary result(this, op1); + m_jit.move(op1.registerID(), result.registerID()); + integerResult(result.gpr(), m_compileIndex); + break; + } + + case DataFormatDouble: { + DoubleOperand op1(this, node.child1); + GPRTemporary result(this); + numberToInt32(op1.fpr(), result.gpr()); + integerResult(result.gpr(), m_compileIndex); + break; + } + + default: { + JSValueOperand op1(this, node.child1); + GPRTemporary result(this, op1); + op1.gpr(); // force op1 to be filled! + result.gpr(); // force result to be allocated! + + switch (operandInfo.registerFormat()) { + case DataFormatNone: + case DataFormatInteger: + case DataFormatDouble: + // The operand has been filled as a JSValue; it cannot be in a !DataFormatJS state. + CRASH(); + + case DataFormatCell: + case DataFormatJS: + case DataFormatJSCell: { + if (op == NumberToInt32) { + FPRTemporary fpTemp(this); + FPRReg fpr = fpTemp.fpr(); + + JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, op1.registerID(), JITCompiler::tagTypeNumberRegister); + + m_jit.move(op1.registerID(), result.registerID()); + m_jit.addPtr(JITCompiler::tagTypeNumberRegister, result.registerID()); + m_jit.movePtrToDouble(result.registerID(), fpTemp.registerID()); + numberToInt32(fpr, result.gpr()); + JITCompiler::Jump wasDouble = m_jit.jump(); + + isInteger.link(&m_jit); + m_jit.zeroExtend32ToPtr(op1.registerID(), result.registerID()); + + wasDouble.link(&m_jit); + } else + valueToInt32(op1, result.gpr()); + integerResult(result.gpr(), m_compileIndex); + break; + } + + case DataFormatJSDouble: { + FPRTemporary fpTemp(this); + m_jit.move(op1.registerID(), result.registerID()); + m_jit.addPtr(JITCompiler::tagTypeNumberRegister, result.registerID()); + m_jit.movePtrToDouble(result.registerID(), fpTemp.registerID()); + numberToInt32(fpTemp.fpr(), result.gpr()); + integerResult(result.gpr(), m_compileIndex); + break; + } + + case DataFormatJSInteger: { + m_jit.move(op1.registerID(), result.registerID()); + jsValueResult(result.gpr(), m_compileIndex, DataFormatJSInteger); + break; + } + } + } + + } + break; + } + + case ValueToNumber: { + ASSERT(!isInt32Constant(node.child1)); + ASSERT(!isDoubleConstant(node.child1)); + GenerationInfo& operandInfo = m_generationInfo[m_jit.graph()[node.child1].virtualRegister]; + switch (operandInfo.registerFormat()) { + case DataFormatNone: + case DataFormatCell: + case DataFormatJS: + case DataFormatJSCell: { + JSValueOperand op1(this, node.child1); + FPRTemporary result(this); + valueToNumber(op1, result.fpr()); + doubleResult(result.fpr(), m_compileIndex); + break; + } + + case DataFormatJSDouble: + case DataFormatDouble: { + DoubleOperand op1(this, node.child1); + FPRTemporary result(this, op1); + m_jit.moveDouble(op1.registerID(), result.registerID()); + doubleResult(result.fpr(), m_compileIndex); + break; + } + + case DataFormatJSInteger: + case DataFormatInteger: { + IntegerOperand op1(this, node.child1); + FPRTemporary result(this); + m_jit.convertInt32ToDouble(op1.registerID(), result.registerID()); + doubleResult(result.fpr(), m_compileIndex); + break; + } + } + break; + } + + case ValueAdd: { + JSValueOperand arg1(this, node.child1); + JSValueOperand arg2(this, node.child2); + GPRReg arg1GPR = arg1.gpr(); + GPRReg arg2GPR = arg2.gpr(); + flushRegisters(); + + GPRResult result(this); + callOperation(operationValueAdd, result.gpr(), arg1GPR, arg2GPR); + + jsValueResult(result.gpr(), m_compileIndex); + break; + } + + case ArithAdd: { + DoubleOperand op1(this, node.child1); + DoubleOperand op2(this, node.child2); + FPRTemporary result(this, op1, op2); + + MacroAssembler::FPRegisterID reg1 = op1.registerID(); + MacroAssembler::FPRegisterID reg2 = op2.registerID(); + m_jit.addDouble(reg1, reg2, result.registerID()); + + doubleResult(result.fpr(), m_compileIndex); + break; + } + + case ArithSub: { + DoubleOperand op1(this, node.child1); + DoubleOperand op2(this, node.child2); + FPRTemporary result(this, op1); + + MacroAssembler::FPRegisterID reg1 = op1.registerID(); + MacroAssembler::FPRegisterID reg2 = op2.registerID(); + m_jit.subDouble(reg1, reg2, result.registerID()); + + doubleResult(result.fpr(), m_compileIndex); + break; + } + + case ArithMul: { + DoubleOperand op1(this, node.child1); + DoubleOperand op2(this, node.child2); + FPRTemporary result(this, op1, op2); + + MacroAssembler::FPRegisterID reg1 = op1.registerID(); + MacroAssembler::FPRegisterID reg2 = op2.registerID(); + m_jit.mulDouble(reg1, reg2, result.registerID()); + + doubleResult(result.fpr(), m_compileIndex); + break; + } + + case ArithDiv: { + DoubleOperand op1(this, node.child1); + DoubleOperand op2(this, node.child2); + FPRTemporary result(this, op1); + + MacroAssembler::FPRegisterID reg1 = op1.registerID(); + MacroAssembler::FPRegisterID reg2 = op2.registerID(); + m_jit.divDouble(reg1, reg2, result.registerID()); + + doubleResult(result.fpr(), m_compileIndex); + break; + } + + case ArithMod: { + DoubleOperand arg1(this, node.child1); + DoubleOperand arg2(this, node.child2); + FPRReg arg1FPR = arg1.fpr(); + FPRReg arg2FPR = arg2.fpr(); + flushRegisters(); + + FPRResult result(this); + callOperation(fmod, result.fpr(), arg1FPR, arg2FPR); + + doubleResult(result.fpr(), m_compileIndex); + break; + } + + case GetByVal: { + JSValueOperand arg1(this, node.child1); + JSValueOperand arg2(this, node.child2); + GPRReg arg1GPR = arg1.gpr(); + GPRReg arg2GPR = arg2.gpr(); + flushRegisters(); + + GPRResult result(this); + callOperation(operationGetByVal, result.gpr(), arg1GPR, arg2GPR); + + jsValueResult(result.gpr(), m_compileIndex); + break; + } + + case PutByVal: + case PutByValAlias: { + JSValueOperand arg1(this, node.child1); + JSValueOperand arg2(this, node.child2); + JSValueOperand arg3(this, node.child3); + GPRReg arg1GPR = arg1.gpr(); + GPRReg arg2GPR = arg2.gpr(); + GPRReg arg3GPR = arg3.gpr(); + flushRegisters(); + + GPRResult result(this); + callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR); + + noResult(m_compileIndex); + break; + } + + case GetById: { + JSValueOperand base(this, node.child1); + GPRReg baseGPR = base.gpr(); + flushRegisters(); + + GPRResult result(this); + callOperation(operationGetById, result.gpr(), baseGPR, identifier(node.identifierNumber())); + jsValueResult(result.gpr(), m_compileIndex); + break; + } + + case PutById: { + JSValueOperand base(this, node.child1); + JSValueOperand value(this, node.child2); + GPRReg valueGPR = value.gpr(); + GPRReg baseGPR = base.gpr(); + flushRegisters(); + + callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdStrict : operationPutByIdNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber())); + noResult(m_compileIndex); + break; + } + + case PutByIdDirect: { + JSValueOperand base(this, node.child1); + JSValueOperand value(this, node.child2); + GPRReg valueGPR = value.gpr(); + GPRReg baseGPR = base.gpr(); + flushRegisters(); + + callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdDirectStrict : operationPutByIdDirectNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber())); + noResult(m_compileIndex); + break; + } + + case GetGlobalVar: { + GPRTemporary result(this); + + JSVariableObject* globalObject = m_jit.codeBlock()->globalObject(); + m_jit.loadPtr(globalObject->addressOfRegisters(), result.registerID()); + m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.registerID(), node.varNumber()), result.registerID()); + + jsValueResult(result.gpr(), m_compileIndex); + break; + } + + case PutGlobalVar: { + JSValueOperand value(this, node.child1); + GPRTemporary temp(this); + + JSVariableObject* globalObject = m_jit.codeBlock()->globalObject(); + m_jit.loadPtr(globalObject->addressOfRegisters(), temp.registerID()); + m_jit.storePtr(value.registerID(), JITCompiler::addressForGlobalVar(temp.registerID(), node.varNumber())); + + noResult(m_compileIndex); + break; + } + + case Return: { + ASSERT(JITCompiler::callFrameRegister != JITCompiler::regT1); + ASSERT(JITCompiler::regT1 != JITCompiler::returnValueRegister); + ASSERT(JITCompiler::returnValueRegister != JITCompiler::callFrameRegister); + + // Return the result in returnValueRegister. + JSValueOperand op1(this, node.child1); + m_jit.move(op1.registerID(), JITCompiler::returnValueRegister); + + // Grab the return address. + m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, JITCompiler::regT1); + // Restore our caller's "r". + m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, JITCompiler::callFrameRegister); + // Return. + m_jit.restoreReturnAddressBeforeReturn(JITCompiler::regT1); + m_jit.ret(); + + noResult(m_compileIndex); + break; + } + } + + if (node.mustGenerate()) + use(m_compileIndex); + + checkConsistency(); +} + +void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator) +{ + ASSERT(!m_compileIndex); + Node* nodes = m_jit.graph().begin(); + + for (; m_compileIndex < m_jit.graph().size(); ++m_compileIndex) { +#if DFG_DEBUG_VERBOSE + fprintf(stderr, "index(%d)\n", (int)m_compileIndex); +#endif + + Node& node = nodes[m_compileIndex]; + if (!node.refCount) + continue; + compile(checkIterator, node); + } +} + +} } // namespace JSC::DFG + +#endif diff --git a/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.h new file mode 100644 index 0000000..e140e45 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGNonSpeculativeJIT_h +#define DFGNonSpeculativeJIT_h + +#if ENABLE(DFG_JIT) + +#include <dfg/DFGJITCodeGenerator.h> + +namespace JSC { namespace DFG { + +class SpeculationCheckIndexIterator; + +// === EntryLocation === +// +// This structure describes an entry point into the non-speculative +// code path. This is used in linking bail-outs from the speculative path. +struct EntryLocation { + EntryLocation(MacroAssembler::Label, NonSpeculativeJIT*); + + // The node this entry point corresponds to, and the label + // marking the start of code for the given node. + MacroAssembler::Label m_entry; + NodeIndex m_nodeIndex; + + // For every entry point we record a map recording for every + // machine register which, if any, values it contains. For + // GPR registers we must also record the format of the value. + struct RegisterInfo { + NodeIndex nodeIndex; + DataFormat format; + }; + RegisterInfo m_gprInfo[numberOfGPRs]; + NodeIndex m_fprInfo[numberOfFPRs]; +}; + +// === NonSpeculativeJIT === +// +// This class is used to generate code for the non-speculative path. +// Code generation will take advantage of static information available +// in the dataflow to perform safe optimizations - for example, avoiding +// boxing numeric values between arithmetic operations, but will not +// perform any unsafe optimizations that would render the code unable +// to produce the correct results for any possible input. +class NonSpeculativeJIT : public JITCodeGenerator { + friend struct EntryLocation; +public: + NonSpeculativeJIT(JITCompiler& jit) + : JITCodeGenerator(jit, false) + { + } + + void compile(SpeculationCheckIndexIterator&); + + typedef SegmentedVector<EntryLocation, 16> EntryLocationVector; + EntryLocationVector& entryLocations() { return m_entryLocations; } + +private: + void compile(SpeculationCheckIndexIterator&, Node&); + + // These methods are used when generating 'unexpected' + // calls out from JIT code to C++ helper routines - + // they spill all live values to the appropriate + // slots in the RegisterFile without changing any state + // in the GenerationInfo. + void silentSpill(VirtualRegister spillMe, GPRReg canTrample) + { + GenerationInfo& info = m_generationInfo[spillMe]; + ASSERT(info.registerFormat() != DataFormatNone); + if (info.needsSpill()) { + DataFormat spillFormat = info.registerFormat(); + + if (spillFormat == DataFormatDouble) { + boxDouble(info.fpr(), canTrample); + m_jit.storePtr(JITCompiler::gprToRegisterID(canTrample), JITCompiler::addressFor(spillMe)); + } else { + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(info.gpr()); + + if (spillFormat == DataFormatInteger) { + m_jit.orPtr(JITCompiler::tagTypeNumberRegister, reg); + m_jit.storePtr(reg, JITCompiler::addressFor(spillMe)); + } else { + ASSERT(spillFormat & DataFormatJS || spillFormat == DataFormatCell); + m_jit.storePtr(reg, JITCompiler::addressFor(spillMe)); + } + } + } + } + void silentFill(VirtualRegister spillMe, GPRReg canTrample) + { + GenerationInfo& info = m_generationInfo[spillMe]; + NodeIndex nodeIndex = info.nodeIndex(); + Node& node = m_jit.graph()[nodeIndex]; + ASSERT(info.registerFormat() != DataFormatNone); + DataFormat spillFormat = info.registerFormat(); + + if (node.isConstant()) { + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(info.gpr()); + m_jit.move(constantAsJSValueAsImmPtr(nodeIndex), reg); + } else if (node.isArgument()) { + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(info.gpr()); + m_jit.loadPtr(m_jit.addressForArgument(m_jit.graph()[nodeIndex].argumentNumber()), reg); + } else if (spillFormat == DataFormatDouble) { + m_jit.loadPtr(JITCompiler::addressFor(spillMe), JITCompiler::gprToRegisterID(canTrample)); + unboxDouble(canTrample, info.fpr()); + } else if (spillFormat == DataFormatInteger) { + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(info.gpr()); + m_jit.load32(JITCompiler::addressFor(spillMe), reg); + } else { + ASSERT(spillFormat & DataFormatJS || spillFormat == DataFormatCell); + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(info.gpr()); + m_jit.loadPtr(JITCompiler::addressFor(spillMe), reg); + } + } + void silentSpillAllRegisters(GPRReg dontTrample) + { + GPRReg canTrample = (dontTrample == gpr0) ? gpr1 : gpr0; + + for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) { + VirtualRegister name = m_gprs.name(gpr); + if (name != InvalidVirtualRegister) + silentSpill(name, canTrample); + } + for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) { + VirtualRegister name = m_fprs.name(fpr); + if (name != InvalidVirtualRegister) + silentSpill(name, canTrample); + } + } + void silentFillAllRegisters(GPRReg dontTrample) + { + GPRReg canTrample = (dontTrample == gpr0) ? gpr1 : gpr0; + + for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) { + VirtualRegister name = m_fprs.name(fpr); + if (name != InvalidVirtualRegister) + silentFill(name, canTrample); + } + for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) { + VirtualRegister name = m_gprs.name(gpr); + if (name != InvalidVirtualRegister) + silentFill(name, canTrample); + } + } + void silentFillAllRegisters(FPRReg dontTrample) + { + GPRReg canTrample = gpr0; + + for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) { + VirtualRegister name = m_fprs.name(fpr); + if (name != InvalidVirtualRegister) { +#ifndef NDEBUG + ASSERT(fpr != dontTrample); +#else + UNUSED_PARAM(dontTrample); +#endif + silentFill(name, canTrample); + } + } + for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) { + VirtualRegister name = m_gprs.name(gpr); + if (name != InvalidVirtualRegister) + silentFill(name, canTrample); + } + } + + // These methods are used to plant calls out to C++ + // helper routines to convert between types. + void valueToNumber(JSValueOperand&, FPRReg result); + void valueToInt32(JSValueOperand&, GPRReg result); + void numberToInt32(FPRReg, GPRReg result); + + // Record an entry location into the non-speculative code path; + // for every bail-out on the speculative path we record information + // to be able to re-enter into the non-speculative one. + void trackEntry(MacroAssembler::Label entry) + { + m_entryLocations.append(EntryLocation(entry, this)); + } + + EntryLocationVector m_entryLocations; +}; + +} } // namespace JSC::DFG + +#endif +#endif + diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp new file mode 100644 index 0000000..de14415 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DFGOperations.h" + +#if ENABLE(DFG_JIT) + +#include "CodeBlock.h" +#include "Interpreter.h" +#include "JSByteArray.h" +#include "JSGlobalData.h" +#include "Operations.h" + +namespace JSC { namespace DFG { + +EncodedJSValue operationConvertThis(ExecState* exec, EncodedJSValue encodedOp) +{ + return JSValue::encode(JSValue::decode(encodedOp).toThisObject(exec)); +} + +EncodedJSValue operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) +{ + JSValue op1 = JSValue::decode(encodedOp1); + JSValue op2 = JSValue::decode(encodedOp2); + + if (op1.isInt32() && op2.isInt32()) { + int64_t result64 = static_cast<int64_t>(op1.asInt32()) + static_cast<int64_t>(op2.asInt32()); + int32_t result32 = static_cast<int32_t>(result64); + if (LIKELY(result32 == result64)) + return JSValue::encode(jsNumber(result32)); + return JSValue::encode(jsNumber((double)result64)); + } + + double number1; + double number2; + if (op1.getNumber(number1) && op2.getNumber(number2)) + return JSValue::encode(jsNumber(number1 + number2)); + + return JSValue::encode(jsAddSlowCase(exec, op1, op2)); +} + +EncodedJSValue operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty) +{ + JSValue baseValue = JSValue::decode(encodedBase); + JSValue property = JSValue::decode(encodedProperty); + + if (LIKELY(baseValue.isCell())) { + JSCell* base = baseValue.asCell(); + + if (property.isUInt32()) { + JSGlobalData* globalData = &exec->globalData(); + uint32_t i = property.asUInt32(); + + // FIXME: the JIT used to handle these in compiled code! + if (isJSArray(globalData, base) && asArray(base)->canGetIndex(i)) + return JSValue::encode(asArray(base)->getIndex(i)); + + // FIXME: the JITstub used to relink this to an optimized form! + if (isJSString(globalData, base) && asString(base)->canGetIndex(i)) + return JSValue::encode(asString(base)->getIndex(exec, i)); + + // FIXME: the JITstub used to relink this to an optimized form! + if (isJSByteArray(globalData, base) && asByteArray(base)->canAccessIndex(i)) + return JSValue::encode(asByteArray(base)->getIndex(exec, i)); + + return JSValue::encode(baseValue.get(exec, i)); + } + + if (property.isString()) { + Identifier propertyName(exec, asString(property)->value(exec)); + PropertySlot slot(base); + if (base->fastGetOwnPropertySlot(exec, propertyName, slot)) + return JSValue::encode(slot.getValue(exec, propertyName)); + } + } + + Identifier ident(exec, property.toString(exec)); + return JSValue::encode(baseValue.get(exec, ident)); +} + +EncodedJSValue operationGetById(ExecState* exec, EncodedJSValue encodedBase, Identifier* identifier) +{ + JSValue baseValue = JSValue::decode(encodedBase); + PropertySlot slot(baseValue); + return JSValue::encode(baseValue.get(exec, *identifier, slot)); +} + +template<bool strict> +ALWAYS_INLINE static void operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) +{ + JSGlobalData* globalData = &exec->globalData(); + + JSValue baseValue = JSValue::decode(encodedBase); + JSValue property = JSValue::decode(encodedProperty); + JSValue value = JSValue::decode(encodedValue); + + if (LIKELY(property.isUInt32())) { + uint32_t i = property.asUInt32(); + + if (isJSArray(globalData, baseValue)) { + JSArray* jsArray = asArray(baseValue); + if (jsArray->canSetIndex(i)) { + jsArray->setIndex(*globalData, i, value); + return; + } + + jsArray->JSArray::put(exec, i, value); + return; + } + + if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { + JSByteArray* jsByteArray = asByteArray(baseValue); + // FIXME: the JITstub used to relink this to an optimized form! + if (value.isInt32()) { + jsByteArray->setIndex(i, value.asInt32()); + return; + } + + double dValue = 0; + if (value.getNumber(dValue)) { + jsByteArray->setIndex(i, dValue); + return; + } + } + + baseValue.put(exec, i, value); + return; + } + + // Don't put to an object if toString throws an exception. + Identifier ident(exec, property.toString(exec)); + if (!globalData->exception) { + PutPropertySlot slot(strict); + baseValue.put(exec, ident, value, slot); + } +} + +void operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) +{ + operationPutByValInternal<true>(exec, encodedBase, encodedProperty, encodedValue); +} + +void operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) +{ + operationPutByValInternal<false>(exec, encodedBase, encodedProperty, encodedValue); +} + +void operationPutByIdStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier) +{ + PutPropertySlot slot(true); + JSValue::decode(encodedBase).put(exec, *identifier, JSValue::decode(encodedValue), slot); +} + +void operationPutByIdNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier) +{ + PutPropertySlot slot(false); + JSValue::decode(encodedBase).put(exec, *identifier, JSValue::decode(encodedValue), slot); +} + +void operationPutByIdDirectStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier) +{ + PutPropertySlot slot(true); + JSValue::decode(encodedBase).putDirect(exec, *identifier, JSValue::decode(encodedValue), slot); +} + +void operationPutByIdDirectNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier) +{ + PutPropertySlot slot(false); + JSValue::decode(encodedBase).putDirect(exec, *identifier, JSValue::decode(encodedValue), slot); +} + +DFGHandler lookupExceptionHandler(ExecState* exec, ReturnAddressPtr faultLocation) +{ + JSValue exceptionValue = exec->exception(); + ASSERT(exceptionValue); + + unsigned vPCIndex = exec->codeBlock()->bytecodeOffset(faultLocation); + HandlerInfo* handler = exec->globalData().interpreter->throwException(exec, exceptionValue, vPCIndex); + + void* catchRoutine = handler ? handler->nativeCode.executableAddress() : (void*)ctiOpThrowNotCaught; + ASSERT(catchRoutine); + return DFGHandler(exec, catchRoutine); +} + +double dfgConvertJSValueToNumber(ExecState* exec, EncodedJSValue value) +{ + return JSValue::decode(value).toNumber(exec); +} + +int32_t dfgConvertJSValueToInt32(ExecState* exec, EncodedJSValue value) +{ + return JSValue::decode(value).toInt32(exec); +} + +} } // namespace JSC::DFG + +#endif diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h new file mode 100644 index 0000000..18570e2 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGOperations.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGOperations_h +#define DFGOperations_h + +#if ENABLE(DFG_JIT) + +#include <dfg/DFGJITCompiler.h> + +namespace JSC { + +class Identifier; + +namespace DFG { + +// These typedefs provide typechecking when generating calls out to helper routines; +// this helps prevent calling a helper routine with the wrong arguments! +typedef EncodedJSValue (*J_DFGOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue); +typedef EncodedJSValue (*J_DFGOperation_EJ)(ExecState*, EncodedJSValue); +typedef EncodedJSValue (*J_DFGOperation_EJP)(ExecState*, EncodedJSValue, void*); +typedef EncodedJSValue (*J_DFGOperation_EJI)(ExecState*, EncodedJSValue, Identifier*); +typedef void (*V_DFGOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue); +typedef void (*V_DFGOperation_EJJP)(ExecState*, EncodedJSValue, EncodedJSValue, void*); +typedef void (*V_DFGOperation_EJJI)(ExecState*, EncodedJSValue, EncodedJSValue, Identifier*); +typedef double (*D_DFGOperation_DD)(double, double); + +// These routines are provide callbacks out to C++ implementations of operations too complex to JIT. +EncodedJSValue operationConvertThis(ExecState*, EncodedJSValue encodedOp1); +EncodedJSValue operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2); +EncodedJSValue operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty); +EncodedJSValue operationGetById(ExecState*, EncodedJSValue encodedBase, Identifier*); +void operationPutByValStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue); +void operationPutByValNonStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue); +void operationPutByIdStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*); +void operationPutByIdNonStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*); +void operationPutByIdDirectStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*); +void operationPutByIdDirectNonStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*); + +// This method is used to lookup an exception hander, keyed by faultLocation, which is +// the return location from one of the calls out to one of the helper operations above. +struct DFGHandler { + DFGHandler(ExecState* exec, void* handler) + : exec(exec) + , handler(handler) + { + } + + ExecState* exec; + void* handler; +}; +DFGHandler lookupExceptionHandler(ExecState*, ReturnAddressPtr faultLocation); + +// These operations implement the implicitly called ToInt32 and ToNumber conversions from ES5. +double dfgConvertJSValueToNumber(ExecState*, EncodedJSValue); +int32_t dfgConvertJSValueToInt32(ExecState*, EncodedJSValue); + +} } // namespace JSC::DFG + +#endif +#endif diff --git a/Source/JavaScriptCore/dfg/DFGRegisterBank.h b/Source/JavaScriptCore/dfg/DFGRegisterBank.h new file mode 100644 index 0000000..575e6b7 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGRegisterBank.h @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGRegisterBank_h +#define DFGRegisterBank_h + +#if ENABLE(DFG_JIT) + +#include <dfg/DFGJITCompiler.h> + +namespace JSC { namespace DFG { + +// === RegisterBank === +// +// This class is used to implement the GPR and FPR register banks. +// All registers have two pieces of state associated with them: +// a lock count (used to indicate this register is already in use +// in code generation of the current node, and cannot be spilled or +// allocated as a temporary), and VirtualRegister 'name', recording +// which value (if any) a machine register currently holds. +// Either or both of these pieces of information may be valid for a +// given register. A register may be: +// +// - unlocked, and unnamed: Available for allocation. +// - locked, but unnamed: Already allocated as a temporary or +// result for the current node. +// - unlocked, but named: Contains the result of a prior operation, +// not yet in use for this node, +// - locked, but named: Contains the result of a prior operation, +// already allocated as a operand to the +// current operation. +// +// For every named register we also record a hint value indicating +// the order in which registers should be selected to be spilled; +// registers that can be more cheaply spilled and/or filled should +// be selected first. +// +// Locking register is a strong retention mechanism; a locked register +// will never be reallocated (this is used to ensure the operands to +// the current node are in registers). Naming, conversely, in a weak +// retention mechanism - allocating a register may force a named value +// to be spilled. +// +// All named values must be given a hint that is greater than Min and +// less than Max. +template<typename RegID, size_t NUM_REGS, typename SpillHint, SpillHint SpillHintMin, SpillHint SpillHintMax> +class RegisterBank { +public: + RegisterBank() + : m_lastAllocated(NUM_REGS - 1) + { + } + + // Allocate a register - this function finds an unlocked register, + // locks it, and returns it. If any named registers exist, one + // of these should be selected to be allocated. If all unlocked + // registers are named, then one of the named registers will need + // to be spilled. In this case the register selected to be spilled + // will be one of the registers that has the lowest 'spillOrder' + // cost associated with it. + // + // This method select the register to be allocated, and calls the + // private 'allocateInternal' method to update internal data + // structures accordingly. + RegID allocate(VirtualRegister &spillMe) + { + uint32_t currentLowest = NUM_REGS; + SpillHint currentSpillOrder = SpillHintMax; + + // Scan through all register, starting at the last allocated & looping around. + ASSERT(m_lastAllocated < NUM_REGS); + + // This loop is broken into two halves, looping from the last allocated + // register (the register returned last time this method was called) to + // the maximum register value, then from 0 to the last allocated. + // This implements a simple round-robin like approach to try to reduce + // thrash, and minimize time spent scanning locked registers in allocation. + // If a unlocked and unnamed register is found return it immediately. + // Otherwise, find the first unlocked register with the lowest spillOrder. + for (uint32_t i = m_lastAllocated + 1; i < NUM_REGS; ++i) { + // (1) If the current register is locked, it is not a candidate. + if (m_data[i].lockCount) + continue; + // (2) If the current register's spill order is 0, pick this! – unassigned registers have spill order 0. + SpillHint spillOrder = m_data[i].spillOrder; + if (!spillOrder) + return allocateInternal(i, spillMe); + // If this register is better (has a lower spill order value) than any prior + // candidate, then record it. + if (spillOrder < currentSpillOrder) { + currentSpillOrder = spillOrder; + currentLowest = i; + } + } + // Loop over the remaining entries. + for (uint32_t i = 0; i <= m_lastAllocated; ++i) { + if (m_data[i].lockCount) + continue; + SpillHint spillOrder = m_data[i].spillOrder; + if (!spillOrder) + return allocateInternal(i, spillMe); + if (spillOrder < currentSpillOrder) { + currentSpillOrder = spillOrder; + currentLowest = i; + } + } + + // Deadlock check - this could only occur is all registers are locked! + ASSERT(currentLowest != NUM_REGS && currentSpillOrder != SpillHintMax); + // There were no available registers; currentLowest will need to be spilled. + return allocateInternal(currentLowest, spillMe); + } + + // retain/release - these methods are used to associate/disassociate names + // with values in registers. retain should only be called on locked registers. + void retain(RegID reg, VirtualRegister name, SpillHint spillOrder) + { + // 'reg' must be a valid, locked register. + ASSERT(reg < NUM_REGS); + ASSERT(m_data[reg].lockCount); + // 'reg' should not currently be named, the new name must be valid. + ASSERT(m_data[reg].name == InvalidVirtualRegister); + ASSERT(name != InvalidVirtualRegister); + // 'reg' should not currently have a spillOrder, the new spill order must be valid. + ASSERT(spillOrder && spillOrder < SpillHintMax); + ASSERT(m_data[reg].spillOrder == SpillHintMin); + + m_data[reg].name = name; + m_data[reg].spillOrder = spillOrder; + } + void release(RegID reg) + { + // 'reg' must be a valid register. + ASSERT(reg < NUM_REGS); + // 'reg' should currently be named. + ASSERT(m_data[reg].name != InvalidVirtualRegister); + // 'reg' should currently have a valid spill order. + ASSERT(m_data[reg].spillOrder > SpillHintMin && m_data[reg].spillOrder < SpillHintMax); + + m_data[reg].name = InvalidVirtualRegister; + m_data[reg].spillOrder = SpillHintMin; + } + + // lock/unlock register, ensures that they are not spilled. + void lock(RegID reg) + { + ASSERT(reg < NUM_REGS); + ++m_data[reg].lockCount; + ASSERT(m_data[reg].lockCount); + } + void unlock(RegID reg) + { + ASSERT(reg < NUM_REGS); + ASSERT(m_data[reg].lockCount); + --m_data[reg].lockCount; + } + bool isLocked(RegID reg) + { + ASSERT(reg < NUM_REGS); + return m_data[reg].lockCount; + } + + // Get the name (VirtualRegister) associated with the + // given register (or InvalidVirtualRegister for none). + VirtualRegister name(RegID reg) + { + ASSERT(reg < NUM_REGS); + return m_data[reg].name; + } + +#ifndef NDEBUG + void dump() + { + // For each register, print the VirtualRegister 'name'. + for (uint32_t i =0; i < NUM_REGS; ++i) { + if (m_data[i].name != InvalidVirtualRegister) + fprintf(stderr, "[%02d]", m_data[i].name); + else + fprintf(stderr, "[--]"); + } + fprintf(stderr, "\n"); + } +#endif + +private: + // Used by 'allocate', above, to update inforamtion in the map. + RegID allocateInternal(uint32_t i, VirtualRegister &spillMe) + { + // 'i' must be a valid, unlocked register. + ASSERT(i < NUM_REGS && !m_data[i].lockCount); + + // Return the VirtualRegister of the named value currently stored in + // the register being returned - or InvalidVirtualRegister if none. + spillMe = m_data[i].name; + + // Clear any name/spillOrder currently associated with the register, + m_data[i] = MapEntry(); + m_data[i].lockCount = 1; + // Mark the register as locked (with a lock count of 1). + m_lastAllocated = i; + return (RegID)i; + } + + // === MapEntry === + // + // This structure provides information for an individual machine register + // being managed by the RegisterBank. For each register we track a lock + // count, name and spillOrder hint. + struct MapEntry { + MapEntry() + : name(InvalidVirtualRegister) + , spillOrder(SpillHintMin) + , lockCount(0) + { + } + + VirtualRegister name; + SpillHint spillOrder; + uint32_t lockCount; + }; + + // Holds the current status of all registers. + MapEntry m_data[NUM_REGS]; + // Used to to implement a simple round-robin like allocation scheme. + uint32_t m_lastAllocated; +}; + +} } // namespace JSC::DFG + +#endif +#endif diff --git a/Source/JavaScriptCore/dfg/DFGScoreBoard.h b/Source/JavaScriptCore/dfg/DFGScoreBoard.h new file mode 100644 index 0000000..eefed9e --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGScoreBoard.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGScoreBoard_h +#define DFGScoreBoard_h + +#if ENABLE(DFG_JIT) + +#include <dfg/DFGGraph.h> +#include <wtf/Vector.h> + +namespace JSC { namespace DFG { + +// === ScoreBoard === +// +// This class is used in performing a virtual register allocation over the graph. +// VirtualRegisters are allocated to nodes, with a used count for each virtual +// register tracking the lifespan of the value; after the final use of a node +// the VirtualRegister associated is freed such that it can be reused for +// another node. +class ScoreBoard { +public: + ScoreBoard(Graph& graph) + : m_graph(graph) + { + } + +#if DFG_CONSISTENCY_CHECK + ~ScoreBoard() + { + // Every VirtualRegister that was allocated should now be free. + ASSERT(m_used.size() == m_free.size()); + // For every entry in the free list, the use count of the virtual register should be zero. + // * By using the virtual register numbers from m_free, we are checking that all values + // in m_free are < m_used.size(), and correspond to an allocated VirtualRegsiter. + // * By setting m_used to a non-zero value after checking it, we are checking that all + // entries in m_free are unique (otherwise the second test of m_used will fail). + for (size_t i = 0; i < m_free.size(); ++i) { + VirtualRegister virtualRegister = m_free[i]; + ASSERT(!m_used[virtualRegister]); + m_used[virtualRegister] = 1; + } + } +#endif + + VirtualRegister allocate() + { + // Do we have any VirtualRegsiters in the free list, that were used by + // prior nodes, but are now available? + if (!m_free.isEmpty()) { + VirtualRegister result = m_free.last(); + m_free.removeLast(); + // Use count must have hit zero for it to have been added to the free list! + ASSERT(!m_used[result]); + return result; + } + + // Allocate a new VirtualRegister, and add a corresponding entry to m_used. + size_t next = allocatedCount(); + m_used.append(0); + return (VirtualRegister)next; + } + + // Increment the usecount for the VirtualRegsiter associated with 'child', + // if it reaches the node's refcount, free the VirtualRegsiter. + void use(NodeIndex child) + { + if (child == NoNode) + return; + + // Find the virtual register number for this child, increment its use count. + Node& node = m_graph[child]; + VirtualRegister index = node.virtualRegister; + if (node.refCount == ++m_used[index]) { + // If the use count in the scoreboard reaches the use count for the node, + // then this was its last use; the virtual register is now free. + // Clear the use count & add to the free list. + m_used[index] = 0; + m_free.append(index); + } + } + + unsigned allocatedCount() + { + // m_used contains an entry for every allocated VirtualRegister. + return m_used.size(); + } + +private: + // The graph, so we can get refCounts for nodes, to determine when values are dead. + Graph& m_graph; + // For every virtual register that has been allocated (either currently alive, or in + // the free list), we keep a count of the number of remaining uses until it is dead + // (0, in the case of entries in the free list). Since there is an entry for every + // allocated VirtualRegister, the length of this array conveniently provides the + // next available VirtualRegister number. + Vector<uint32_t, 64> m_used; + // A free list of VirtualRegsiters no longer alive. + Vector<VirtualRegister, 64> m_free; +}; + +} } // namespace JSC::DFG + +#endif +#endif diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp new file mode 100644 index 0000000..95472e1 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -0,0 +1,663 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DFGSpeculativeJIT.h" + +#if ENABLE(DFG_JIT) + +namespace JSC { namespace DFG { + +template<bool strict> +GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat& returnFormat) +{ + Node& node = m_jit.graph()[nodeIndex]; + VirtualRegister virtualRegister = node.virtualRegister; + GenerationInfo& info = m_generationInfo[virtualRegister]; + + switch (info.registerFormat()) { + case DataFormatNone: { + GPRReg gpr = allocate(); + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); + + if (node.isConstant()) { + m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); + if (isInt32Constant(nodeIndex)) { + m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), reg); + info.fillInteger(gpr); + returnFormat = DataFormatInteger; + return gpr; + } + m_jit.move(constantAsJSValueAsImmPtr(nodeIndex), reg); + } else if (node.isArgument()) { + m_gprs.retain(gpr, virtualRegister, SpillOrderArgument); + m_jit.loadPtr(m_jit.addressForArgument(m_jit.graph()[nodeIndex].argumentNumber()), reg); + } else { + DataFormat spillFormat = info.spillFormat(); + ASSERT(spillFormat & DataFormatJS); + + m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); + + if (spillFormat == DataFormatJSInteger) { + // If we know this was spilled as an integer we can fill without checking. + if (strict) { + m_jit.load32(JITCompiler::addressFor(virtualRegister), reg); + info.fillInteger(gpr); + returnFormat = DataFormatInteger; + return gpr; + } + m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg); + info.fillJSValue(gpr, DataFormatJSInteger); + returnFormat = DataFormatJSInteger; + return gpr; + } + m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg); + } + + // Fill as JSValue, and fall through. + info.fillJSValue(gpr, DataFormatJSInteger); + m_gprs.unlock(gpr); + } + + case DataFormatJS: { + // Check the value is an integer. + GPRReg gpr = info.gpr(); + m_gprs.lock(gpr); + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); + speculationCheck(m_jit.branchPtr(MacroAssembler::Below, reg, JITCompiler::tagTypeNumberRegister)); + info.fillJSValue(gpr, DataFormatJSInteger); + // If !strict we're done, return. + if (!strict) { + returnFormat = DataFormatJSInteger; + return gpr; + } + // else fall through & handle as DataFormatJSInteger. + m_gprs.unlock(gpr); + } + + case DataFormatJSInteger: { + // In a strict fill we need to strip off the value tag. + if (strict) { + GPRReg gpr = info.gpr(); + GPRReg result; + // If the register has already been locked we need to take a copy. + // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger. + if (m_gprs.isLocked(gpr)) + result = allocate(); + else { + m_gprs.lock(gpr); + info.fillInteger(gpr); + result = gpr; + } + m_jit.zeroExtend32ToPtr(JITCompiler::gprToRegisterID(gpr), JITCompiler::gprToRegisterID(result)); + returnFormat = DataFormatInteger; + return result; + } + + GPRReg gpr = info.gpr(); + m_gprs.lock(gpr); + returnFormat = DataFormatJSInteger; + return gpr; + } + + case DataFormatInteger: { + GPRReg gpr = info.gpr(); + m_gprs.lock(gpr); + returnFormat = DataFormatInteger; + return gpr; + } + + case DataFormatDouble: + case DataFormatCell: + case DataFormatJSDouble: + case DataFormatJSCell: { + terminateSpeculativeExecution(); + returnFormat = DataFormatInteger; + return allocate(); + } + } + + ASSERT_NOT_REACHED(); + return InvalidGPRReg; +} + +SpeculationCheck::SpeculationCheck(MacroAssembler::Jump check, SpeculativeJIT* jit, unsigned recoveryIndex) + : m_check(check) + , m_nodeIndex(jit->m_compileIndex) + , m_recoveryIndex(recoveryIndex) +{ + for (GPRReg gpr = gpr0; gpr < numberOfGPRs; next(gpr)) { + VirtualRegister virtualRegister = jit->m_gprs.name(gpr); + if (virtualRegister != InvalidVirtualRegister) { + GenerationInfo& info = jit->m_generationInfo[virtualRegister]; + m_gprInfo[gpr].nodeIndex = info.nodeIndex(); + m_gprInfo[gpr].format = info.registerFormat(); + } else + m_gprInfo[gpr].nodeIndex = NoNode; + } + for (FPRReg fpr = fpr0; fpr < numberOfFPRs; next(fpr)) { + VirtualRegister virtualRegister = jit->m_fprs.name(fpr); + if (virtualRegister != InvalidVirtualRegister) { + GenerationInfo& info = jit->m_generationInfo[virtualRegister]; + ASSERT(info.registerFormat() == DataFormatDouble); + m_fprInfo[fpr] = info.nodeIndex(); + } else + m_fprInfo[fpr] = NoNode; + } +} + +GPRReg SpeculativeJIT::fillSpeculateInt(NodeIndex nodeIndex, DataFormat& returnFormat) +{ + return fillSpeculateIntInternal<false>(nodeIndex, returnFormat); +} + +GPRReg SpeculativeJIT::fillSpeculateIntStrict(NodeIndex nodeIndex) +{ + DataFormat mustBeDataFormatInteger; + GPRReg result = fillSpeculateIntInternal<true>(nodeIndex, mustBeDataFormatInteger); + ASSERT(mustBeDataFormatInteger == DataFormatInteger); + return result; +} + +GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex) +{ + Node& node = m_jit.graph()[nodeIndex]; + VirtualRegister virtualRegister = node.virtualRegister; + GenerationInfo& info = m_generationInfo[virtualRegister]; + + switch (info.registerFormat()) { + case DataFormatNone: { + GPRReg gpr = allocate(); + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); + + if (node.isConstant()) { + m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); + JSValue jsValue = constantAsJSValue(nodeIndex); + if (jsValue.isCell()) { + m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), reg); + info.fillJSValue(gpr, DataFormatJSCell); + return gpr; + } + terminateSpeculativeExecution(); + return gpr; + } + if (node.isArgument()) { + m_gprs.retain(gpr, virtualRegister, SpillOrderArgument); + m_jit.loadPtr(m_jit.addressForArgument(m_jit.graph()[nodeIndex].argumentNumber()), reg); + speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, reg, JITCompiler::tagMaskRegister)); + info.fillJSValue(gpr, DataFormatJSCell); + return gpr; + } + ASSERT(info.spillFormat() & DataFormatJS); + m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); + m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), reg); + + if (info.spillFormat() != DataFormatJSCell) + speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, reg, JITCompiler::tagMaskRegister)); + info.fillJSValue(gpr, DataFormatJSCell); + return gpr; + } + + case DataFormatCell: + case DataFormatJSCell: { + GPRReg gpr = info.gpr(); + m_gprs.lock(gpr); + return gpr; + } + + case DataFormatJS: { + GPRReg gpr = info.gpr(); + m_gprs.lock(gpr); + JITCompiler::RegisterID reg = JITCompiler::gprToRegisterID(gpr); + speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, reg, JITCompiler::tagMaskRegister)); + info.fillJSValue(gpr, DataFormatJSCell); + return gpr; + } + + case DataFormatJSInteger: + case DataFormatInteger: + case DataFormatJSDouble: + case DataFormatDouble: { + terminateSpeculativeExecution(); + return allocate(); + } + } + + ASSERT_NOT_REACHED(); + return InvalidGPRReg; +} + +bool SpeculativeJIT::compile(Node& node) +{ + checkConsistency(); + + NodeType op = node.op; + + switch (op) { + case Int32Constant: + case DoubleConstant: + case JSConstant: + initConstantInfo(m_compileIndex); + break; + + case Argument: + initArgumentInfo(m_compileIndex); + break; + + case BitAnd: + case BitOr: + case BitXor: + if (isInt32Constant(node.child1)) { + SpeculateIntegerOperand op2(this, node.child2); + GPRTemporary result(this, op2); + + bitOp(op, valueOfInt32Constant(node.child1), op2.registerID(), result.registerID()); + + integerResult(result.gpr(), m_compileIndex); + } else if (isInt32Constant(node.child2)) { + SpeculateIntegerOperand op1(this, node.child1); + GPRTemporary result(this, op1); + + bitOp(op, valueOfInt32Constant(node.child2), op1.registerID(), result.registerID()); + + integerResult(result.gpr(), m_compileIndex); + } else { + SpeculateIntegerOperand op1(this, node.child1); + SpeculateIntegerOperand op2(this, node.child2); + GPRTemporary result(this, op1, op2); + + MacroAssembler::RegisterID reg1 = op1.registerID(); + MacroAssembler::RegisterID reg2 = op2.registerID(); + bitOp(op, reg1, reg2, result.registerID()); + + integerResult(result.gpr(), m_compileIndex); + } + break; + + case BitRShift: + case BitLShift: + case BitURShift: + if (isInt32Constant(node.child2)) { + SpeculateIntegerOperand op1(this, node.child1); + GPRTemporary result(this, op1); + + shiftOp(op, op1.registerID(), valueOfInt32Constant(node.child2) & 0x1f, result.registerID()); + + integerResult(result.gpr(), m_compileIndex); + } else { + // Do not allow shift amount to be used as the result, MacroAssembler does not permit this. + SpeculateIntegerOperand op1(this, node.child1); + SpeculateIntegerOperand op2(this, node.child2); + GPRTemporary result(this, op1); + + MacroAssembler::RegisterID reg1 = op1.registerID(); + MacroAssembler::RegisterID reg2 = op2.registerID(); + shiftOp(op, reg1, reg2, result.registerID()); + + integerResult(result.gpr(), m_compileIndex); + } + break; + + case UInt32ToNumber: { + IntegerOperand op1(this, node.child1); + GPRTemporary result(this, op1); + + // Test the operand is positive. + speculationCheck(m_jit.branch32(MacroAssembler::LessThan, op1.registerID(), TrustedImm32(0))); + + m_jit.move(op1.registerID(), result.registerID()); + integerResult(result.gpr(), m_compileIndex, op1.format()); + break; + } + + case NumberToInt32: { + SpeculateIntegerOperand op1(this, node.child1); + GPRTemporary result(this, op1); + m_jit.move(op1.registerID(), result.registerID()); + integerResult(result.gpr(), m_compileIndex, op1.format()); + break; + } + + case Int32ToNumber: { + SpeculateIntegerOperand op1(this, node.child1); + GPRTemporary result(this, op1); + m_jit.move(op1.registerID(), result.registerID()); + integerResult(result.gpr(), m_compileIndex, op1.format()); + break; + } + case ValueToInt32: { + SpeculateIntegerOperand op1(this, node.child1); + GPRTemporary result(this, op1); + m_jit.move(op1.registerID(), result.registerID()); + integerResult(result.gpr(), m_compileIndex, op1.format()); + break; + } + + case ValueToNumber: { + SpeculateIntegerOperand op1(this, node.child1); + GPRTemporary result(this, op1); + m_jit.move(op1.registerID(), result.registerID()); + integerResult(result.gpr(), m_compileIndex, op1.format()); + break; + } + + case ValueAdd: + case ArithAdd: { + SpeculateIntegerOperand op1(this, node.child1); + SpeculateIntegerOperand op2(this, node.child2); + GPRTemporary result(this, op1, op2); + + GPRReg gpr1 = op1.gpr(); + GPRReg gpr2 = op2.gpr(); + GPRReg gprResult = result.gpr(); + MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, JITCompiler::gprToRegisterID(gpr1), JITCompiler::gprToRegisterID(gpr2), JITCompiler::gprToRegisterID(gprResult)); + + if (gpr1 == gprResult) + speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2)); + else if (gpr2 == gprResult) + speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1)); + else + speculationCheck(check); + + integerResult(gprResult, m_compileIndex); + break; + } + + case ArithSub: { + SpeculateIntegerOperand op1(this, node.child1); + SpeculateIntegerOperand op2(this, node.child2); + GPRTemporary result(this); + + MacroAssembler::RegisterID reg1 = op1.registerID(); + MacroAssembler::RegisterID reg2 = op2.registerID(); + speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, reg1, reg2, result.registerID())); + + integerResult(result.gpr(), m_compileIndex); + break; + } + + case ArithMul: { + SpeculateIntegerOperand op1(this, node.child1); + SpeculateIntegerOperand op2(this, node.child2); + GPRTemporary result(this); + + MacroAssembler::RegisterID reg1 = op1.registerID(); + MacroAssembler::RegisterID reg2 = op2.registerID(); + speculationCheck(m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.registerID())); + speculationCheck(m_jit.branchTest32(MacroAssembler::Zero, result.registerID())); + + integerResult(result.gpr(), m_compileIndex); + break; + } + + case ArithDiv: { + SpeculateIntegerOperand op1(this, node.child1); + SpeculateIntegerOperand op2(this, node.child2); + GPRTemporary result(this, op1, op2); + + terminateSpeculativeExecution(); + + integerResult(result.gpr(), m_compileIndex); + break; + } + + case ArithMod: { + SpeculateIntegerOperand op1(this, node.child1); + SpeculateIntegerOperand op2(this, node.child2); + GPRTemporary result(this, op1, op2); + + terminateSpeculativeExecution(); + + integerResult(result.gpr(), m_compileIndex); + break; + } + + case GetByVal: { + NodeIndex alias = node.child3; + if (alias != NoNode) { + // FIXME: result should be able to reuse child1, child2. Should have an 'UnusedOperand' type. + JSValueOperand aliasedValue(this, node.child3); + GPRTemporary result(this, aliasedValue); + m_jit.move(aliasedValue.registerID(), result.registerID()); + jsValueResult(result.gpr(), m_compileIndex); + break; + } + + SpeculateCellOperand base(this, node.child1); + SpeculateStrictInt32Operand property(this, node.child2); + GPRTemporary storage(this); + + MacroAssembler::RegisterID baseReg = base.registerID(); + MacroAssembler::RegisterID propertyReg = property.registerID(); + MacroAssembler::RegisterID storageReg = storage.registerID(); + + // Get the array storage. We haven't yet checked this is a JSArray, so this is only safe if + // an access with offset JSArray::storageOffset() is valid for all JSCells! + m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg); + + // Check that base is an array, and that property is contained within m_vector (< m_vectorLength). + speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); + speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()))); + + // FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache + // the storage pointer - especially if there happens to be another register free right now. If we do so, + // then we'll need to allocate a new temporary for result. + GPRTemporary& result = storage; + m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.registerID()); + speculationCheck(m_jit.branchTestPtr(MacroAssembler::Zero, result.registerID())); + + jsValueResult(result.gpr(), m_compileIndex); + break; + } + + case PutByVal: + case PutByValAlias: { + SpeculateStrictInt32Operand property(this, node.child2); + GPRTemporary storage(this); + + MacroAssembler::RegisterID propertyReg; + MacroAssembler::RegisterID storageReg; + + // This block also defines the scope for base, and all bails to the non-speculative path. + // At the end of this scope base will be release, and as such may be reused by for 'value'. + // + // If we've already read from this location on the speculative pass, then it cannot be beyond array bounds, or a hole. + if (op == PutByValAlias) { + SpeculateCellOperand base(this, node.child1); + + // Map base & property into registers, allocate a register for storage. + propertyReg = property.registerID(); + storageReg = storage.registerID(); + MacroAssembler::RegisterID baseReg = base.registerID(); + + // Get the array storage. + m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg); + } else { + SpeculateCellOperand base(this, node.child1); + + // Map base & property into registers, allocate a register for storage. + propertyReg = property.registerID(); + storageReg = storage.registerID(); + MacroAssembler::RegisterID baseReg = base.registerID(); + + // Check that base is an array, and that property is contained within m_vector (< m_vectorLength). + speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr))); + speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()))); + + // Get the array storage. + m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg); + + // Check if we're writing to a hole; if so increment m_numValuesInVector. + MacroAssembler::Jump notHoleValue = m_jit.branchTestPtr(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); + m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); + + // If we're writing to a hole we might be growing the array; + MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length))); + m_jit.add32(TrustedImm32(1), propertyReg); + m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length))); + m_jit.sub32(TrustedImm32(1), propertyReg); + + lengthDoesNotNeedUpdate.link(&m_jit); + notHoleValue.link(&m_jit); + } + // After this point base goes out of scope. This may free the register. + // As such, after this point we'd better not have any bails out to the non-speculative path! + + // Store the value to the array. + JSValueOperand value(this, node.child3); + MacroAssembler::RegisterID valueReg = value.registerID(); + m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); + + noResult(m_compileIndex); + break; + } + + case Return: { + ASSERT(JITCompiler::callFrameRegister != JITCompiler::regT1); + ASSERT(JITCompiler::regT1 != JITCompiler::returnValueRegister); + ASSERT(JITCompiler::returnValueRegister != JITCompiler::callFrameRegister); + + // Return the result in returnValueRegister. + JSValueOperand op1(this, node.child1); + m_jit.move(op1.registerID(), JITCompiler::returnValueRegister); + + // Grab the return address. + m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, JITCompiler::regT1); + // Restore our caller's "r". + m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, JITCompiler::callFrameRegister); + // Return. + m_jit.restoreReturnAddressBeforeReturn(JITCompiler::regT1); + m_jit.ret(); + + noResult(m_compileIndex); + break; + } + + case ConvertThis: { + SpeculateCellOperand thisValue(this, node.child1); + GPRTemporary temp(this); + + m_jit.loadPtr(JITCompiler::Address(thisValue.registerID(), JSCell::structureOffset()), temp.registerID()); + speculationCheck(m_jit.branchTest8(JITCompiler::NonZero, JITCompiler::Address(temp.registerID(), Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(NeedsThisConversion))); + + cellResult(thisValue.gpr(), m_compileIndex); + break; + } + + case GetById: { + JSValueOperand base(this, node.child1); + GPRReg baseGPR = base.gpr(); + flushRegisters(); + + GPRResult result(this); + callOperation(operationGetById, result.gpr(), baseGPR, identifier(node.identifierNumber())); + jsValueResult(result.gpr(), m_compileIndex); + break; + } + + case PutById: { + JSValueOperand base(this, node.child1); + JSValueOperand value(this, node.child2); + GPRReg valueGPR = value.gpr(); + GPRReg baseGPR = base.gpr(); + flushRegisters(); + + callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdStrict : operationPutByIdNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber())); + noResult(m_compileIndex); + break; + } + + case PutByIdDirect: { + JSValueOperand base(this, node.child1); + JSValueOperand value(this, node.child2); + GPRReg valueGPR = value.gpr(); + GPRReg baseGPR = base.gpr(); + flushRegisters(); + + callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdDirectStrict : operationPutByIdDirectNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber())); + noResult(m_compileIndex); + break; + } + + case GetGlobalVar: { + GPRTemporary result(this); + + JSVariableObject* globalObject = m_jit.codeBlock()->globalObject(); + m_jit.loadPtr(globalObject->addressOfRegisters(), result.registerID()); + m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.registerID(), node.varNumber()), result.registerID()); + + jsValueResult(result.gpr(), m_compileIndex); + break; + } + + case PutGlobalVar: { + JSValueOperand value(this, node.child1); + GPRTemporary temp(this); + + JSVariableObject* globalObject = m_jit.codeBlock()->globalObject(); + m_jit.loadPtr(globalObject->addressOfRegisters(), temp.registerID()); + m_jit.storePtr(value.registerID(), JITCompiler::addressForGlobalVar(temp.registerID(), node.varNumber())); + + noResult(m_compileIndex); + break; + } + } + + // Check if generation for the speculative path has failed catastrophically. :-) + // In the future, we may want to throw away the code we've generated in this case. + // For now, there is no point generating any further code, return immediately. + if (m_didTerminate) + return false; + + if (node.mustGenerate()) + use(m_compileIndex); + + checkConsistency(); + + return true; +} + +bool SpeculativeJIT::compile() +{ + ASSERT(!m_compileIndex); + Node* nodes = m_jit.graph().begin(); + + for (; m_compileIndex < m_jit.graph().size(); ++m_compileIndex) { +#if DFG_DEBUG_VERBOSE + fprintf(stderr, "index(%d)\n", (int)m_compileIndex); +#endif + + Node& node = nodes[m_compileIndex]; + if (!node.refCount) + continue; + if (!compile(node)) + return false; + } + return true; +} + +} } // namespace JSC::DFG + +#endif diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h new file mode 100644 index 0000000..93983c6 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DFGSpeculativeJIT_h +#define DFGSpeculativeJIT_h + +#if ENABLE(DFG_JIT) + +#include <dfg/DFGJITCodeGenerator.h> + +namespace JSC { namespace DFG { + +class SpeculativeJIT; + +// This enum describes the types of additional recovery that +// may need be performed should a speculation check fail. +enum SpeculationRecoveryType { + SpeculativeAdd +}; + +// === SpeculationRecovery === +// +// This class provides additional information that may be associated with a +// speculation check - for example +class SpeculationRecovery { +public: + SpeculationRecovery(SpeculationRecoveryType type, GPRReg dest, GPRReg src) + : m_type(type) + , m_dest(dest) + , m_src(src) + { + } + + SpeculationRecoveryType type() { return m_type; } + GPRReg dest() { return m_dest; } + GPRReg src() { return m_src; } + +private: + // Indicates the type of additional recovery to be performed. + SpeculationRecoveryType m_type; + // different recovery types may required different additional information here. + GPRReg m_dest; + GPRReg m_src; +}; + +// === SpeculationCheck === +// +// This structure records a bail-out from the speculative path, +// which will need to be linked in to the non-speculative one. +struct SpeculationCheck { + SpeculationCheck(MacroAssembler::Jump, SpeculativeJIT*, unsigned recoveryIndex = 0); + + // The location of the jump out from the speculative path, + // and the node we were generating code for. + MacroAssembler::Jump m_check; + NodeIndex m_nodeIndex; + // Used to record any additional recovery to be performed; this + // value is an index into the SpeculativeJIT's m_speculationRecoveryList + // array, offset by 1. (m_recoveryIndex == 0) means no recovery. + unsigned m_recoveryIndex; + + struct RegisterInfo { + NodeIndex nodeIndex; + DataFormat format; + }; + RegisterInfo m_gprInfo[numberOfGPRs]; + NodeIndex m_fprInfo[numberOfFPRs]; +}; + + +// === SpeculativeJIT === +// +// The SpeculativeJIT is used to generate a fast, but potentially +// incomplete code path for the dataflow. When code generating +// we may make assumptions about operand types, dynamically check, +// and bail-out to an alternate code path if these checks fail. +// Importantly, the speculative code path cannot be reentered once +// a speculative check has failed. This allows the SpeculativeJIT +// to propagate type information (including information that has +// only speculatively been asserted) through the dataflow. +class SpeculativeJIT : public JITCodeGenerator { + friend struct SpeculationCheck; +public: + // The speculation + typedef SegmentedVector<SpeculationCheck, 16> SpeculationCheckVector; + + SpeculativeJIT(JITCompiler& jit) + : JITCodeGenerator(jit, true) + , m_didTerminate(false) + { + } + + bool compile(); + + // Retrieve the list of bail-outs from the speculative path, + // and additional recovery information. + SpeculationCheckVector& speculationChecks() + { + return m_speculationChecks; + } + SpeculationRecovery* speculationRecovery(size_t index) + { + // SpeculationCheck::m_recoveryIndex is offset by 1, + // 0 means no recovery. + return index ? &m_speculationRecoveryList[index - 1] : 0; + } + + // Called by the speculative operand types, below, to fill operand to + // machine registers, implicitly generating speculation checks as needed. + GPRReg fillSpeculateInt(NodeIndex, DataFormat& returnFormat); + GPRReg fillSpeculateIntStrict(NodeIndex); + GPRReg fillSpeculateCell(NodeIndex); + +private: + bool compile(Node&); + + // Add a speculation check without additional recovery. + void speculationCheck(MacroAssembler::Jump jumpToFail) + { + m_speculationChecks.append(SpeculationCheck(jumpToFail, this)); + } + // Add a speculation check with additional recovery. + void speculationCheck(MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) + { + m_speculationRecoveryList.append(recovery); + m_speculationChecks.append(SpeculationCheck(jumpToFail, this, m_speculationRecoveryList.size())); + } + + // Called when we statically determine that a speculation will fail. + void terminateSpeculativeExecution() + { + // FIXME: in cases where we can statically determine we're going to bail out from the speculative + // JIT we should probably rewind code generation and only produce the non-speculative path. + m_didTerminate = true; + speculationCheck(m_jit.jump()); + } + + template<bool strict> + GPRReg fillSpeculateIntInternal(NodeIndex, DataFormat& returnFormat); + + // It is possible, during speculative generation, to reach a situation in which we + // can statically determine a speculation will fail (for example, when two nodes + // will make conflicting speculations about the same operand). In such cases this + // flag is set, indicating no further code generation should take place. + bool m_didTerminate; + // This vector tracks bail-outs from the speculative path to the non-speculative one. + SpeculationCheckVector m_speculationChecks; + // Some bail-outs need to record additional information recording specific recovery + // to be performed (for example, on detected overflow from an add, we may need to + // reverse the addition if an operand is being overwritten). + Vector<SpeculationRecovery, 16> m_speculationRecoveryList; +}; + + +// === Speculative Operand types === +// +// SpeculateIntegerOperand, SpeculateStrictInt32Operand and SpeculateCellOperand. +// +// These are used to lock the operands to a node into machine registers within the +// SpeculativeJIT. The classes operate like those provided by the JITCodeGenerator, +// however these will perform a speculative check for a more restrictive type than +// we can statically determine the operand to have. If the operand does not have +// the requested type, a bail-out to the non-speculative path will be taken. + +class SpeculateIntegerOperand { +public: + explicit SpeculateIntegerOperand(SpeculativeJIT* jit, NodeIndex index) + : m_jit(jit) + , m_index(index) + , m_gprOrInvalid(InvalidGPRReg) +#ifndef NDEBUG + , m_format(DataFormatNone) +#endif + { + ASSERT(m_jit); + if (jit->isFilled(index)) + gpr(); + } + + ~SpeculateIntegerOperand() + { + ASSERT(m_gprOrInvalid != InvalidGPRReg); + m_jit->unlock(m_gprOrInvalid); + } + + NodeIndex index() const + { + return m_index; + } + + GPRReg gpr() + { + if (m_gprOrInvalid == InvalidGPRReg) + m_gprOrInvalid = m_jit->fillSpeculateInt(index(), m_format); + return m_gprOrInvalid; + } + + DataFormat format() + { + gpr(); // m_format is set when m_gpr is locked. + ASSERT(m_format == DataFormatInteger || m_format == DataFormatJSInteger); + return m_format; + } + + MacroAssembler::RegisterID registerID() + { + return JITCompiler::gprToRegisterID(gpr()); + } + +private: + SpeculativeJIT* m_jit; + NodeIndex m_index; + GPRReg m_gprOrInvalid; + DataFormat m_format; +}; + +class SpeculateStrictInt32Operand { +public: + explicit SpeculateStrictInt32Operand(SpeculativeJIT* jit, NodeIndex index) + : m_jit(jit) + , m_index(index) + , m_gprOrInvalid(InvalidGPRReg) + { + ASSERT(m_jit); + if (jit->isFilled(index)) + gpr(); + } + + ~SpeculateStrictInt32Operand() + { + ASSERT(m_gprOrInvalid != InvalidGPRReg); + m_jit->unlock(m_gprOrInvalid); + } + + NodeIndex index() const + { + return m_index; + } + + GPRReg gpr() + { + if (m_gprOrInvalid == InvalidGPRReg) + m_gprOrInvalid = m_jit->fillSpeculateIntStrict(index()); + return m_gprOrInvalid; + } + + MacroAssembler::RegisterID registerID() + { + return JITCompiler::gprToRegisterID(gpr()); + } + +private: + SpeculativeJIT* m_jit; + NodeIndex m_index; + GPRReg m_gprOrInvalid; +}; + +class SpeculateCellOperand { +public: + explicit SpeculateCellOperand(SpeculativeJIT* jit, NodeIndex index) + : m_jit(jit) + , m_index(index) + , m_gprOrInvalid(InvalidGPRReg) + { + ASSERT(m_jit); + if (jit->isFilled(index)) + gpr(); + } + + ~SpeculateCellOperand() + { + ASSERT(m_gprOrInvalid != InvalidGPRReg); + m_jit->unlock(m_gprOrInvalid); + } + + NodeIndex index() const + { + return m_index; + } + + GPRReg gpr() + { + if (m_gprOrInvalid == InvalidGPRReg) + m_gprOrInvalid = m_jit->fillSpeculateCell(index()); + return m_gprOrInvalid; + } + + MacroAssembler::RegisterID registerID() + { + return JITCompiler::gprToRegisterID(gpr()); + } + +private: + SpeculativeJIT* m_jit; + NodeIndex m_index; + GPRReg m_gprOrInvalid; +}; + + +// === SpeculationCheckIndexIterator === +// +// This class is used by the non-speculative JIT to check which +// nodes require entry points from the speculative path. +class SpeculationCheckIndexIterator { +public: + SpeculationCheckIndexIterator(SpeculativeJIT& speculativeJIT) + : m_speculationChecks(speculativeJIT.speculationChecks()) + , m_iter(m_speculationChecks.begin()) + , m_end(m_speculationChecks.end()) + { + } + + bool hasCheckAtIndex(NodeIndex nodeIndex) + { + while (m_iter != m_end) { + NodeIndex current = m_iter->m_nodeIndex; + if (current >= nodeIndex) + return current == nodeIndex; + ++m_iter; + } + return false; + } + +private: + SpeculativeJIT::SpeculationCheckVector& m_speculationChecks; + SpeculativeJIT::SpeculationCheckVector::Iterator m_iter; + SpeculativeJIT::SpeculationCheckVector::Iterator m_end; +}; + +} } // namespace JSC::DFG + +#endif +#endif + diff --git a/Source/JavaScriptCore/gyp/JavaScriptCore.gyp b/Source/JavaScriptCore/gyp/JavaScriptCore.gyp index 1e46094..a520344 100644 --- a/Source/JavaScriptCore/gyp/JavaScriptCore.gyp +++ b/Source/JavaScriptCore/gyp/JavaScriptCore.gyp @@ -3,30 +3,43 @@ '../../gyp/common.gypi', '../JavaScriptCore.gypi', ], - 'xcode_config_file': '<(DEPTH)/JavaScriptCore/Configurations/DebugRelease.xcconfig', + 'configurations': { + 'Production': { + 'xcode_config_file': '<(project_dir)/Configurations/Base.xcconfig', + }, + 'Profiling': { + 'xcode_config_file': '<(project_dir)/Configurations/DebugRelease.xcconfig', + 'xcode_settings': { + 'STRIP_INSTALLED_PRODUCT': 'NO', + }, + }, + 'Release': { + 'xcode_config_file': '<(project_dir)/Configurations/DebugRelease.xcconfig', + 'xcode_settings': { + 'STRIP_INSTALLED_PRODUCT': 'NO', + }, + }, + 'Debug': { + 'xcode_config_file': '<(project_dir)/Configurations/DebugRelease.xcconfig', + 'xcode_settings': { + 'DEAD_CODE_STRIPPING': '$(DEAD_CODE_STRIPPING_debug)', + 'DEBUG_DEFINES': '$(DEBUG_DEFINES_debug)', + 'GCC_OPTIMIZATION_LEVEL': '$(GCC_OPTIMIZATION_LEVEL_debug)', + 'STRIP_INSTALLED_PRODUCT': '$(STRIP_INSTALLED_PRODUCT_debug)', + }, + }, + }, 'variables': { - # FIXME: We should use a header map instead of listing these explicitly. 'javascriptcore_include_dirs': [ - '<(DEPTH)', # Some paths in API include JavaScriptCore/ - '<(DEPTH)/JavaScriptCore', - '<(DEPTH)/JavaScriptCore/ForwardingHeaders', - '<(DEPTH)/JavaScriptCore/API', - '<(DEPTH)/JavaScriptCore/assembler', - '<(DEPTH)/JavaScriptCore/collector/handles', - '<(DEPTH)/JavaScriptCore/bytecode', - '<(DEPTH)/JavaScriptCore/bytecompiler', - '<(DEPTH)/JavaScriptCore/debugger', - '<(DEPTH)/JavaScriptCore/icu', - '<(DEPTH)/JavaScriptCore/interpreter', - '<(DEPTH)/JavaScriptCore/jit', - '<(DEPTH)/JavaScriptCore/parser', - '<(DEPTH)/JavaScriptCore/profiler', - '<(DEPTH)/JavaScriptCore/runtime', - '<(DEPTH)/JavaScriptCore/wtf', - '<(DEPTH)/JavaScriptCore/wtf/unicode', - '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore', + '<(project_dir)', + '<(project_dir)/icu', ], }, + 'target_defaults': { + 'configurations': { + 'Profiling': {}, + }, + }, 'targets': [ { 'target_name': 'JavaScriptCore', @@ -37,15 +50,22 @@ ], 'include_dirs': [ '<@(javascriptcore_include_dirs)', + '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore', ], + 'configurations': { + 'Production': { + 'INSTALL_PATH': '$(BUILT_PRODUCTS_DIR)', + }, + }, 'sources': [ '<@(javascriptcore_files)', '<@(javascriptcore_publicheader_files)', '<@(javascriptcore_privateheader_files)', + '<@(javascriptcore_derived_source_files)', '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework', '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', - 'libicucore.dylib', - 'libobjc.dylib', + '/usr/lib/libicucore.dylib', + '/usr/lib/libobjc.dylib', ], 'mac_framework_headers': [ '<@(javascriptcore_publicheader_files)', @@ -53,47 +73,41 @@ 'mac_framework_private_headers': [ '<@(javascriptcore_privateheader_files)', ], - 'xcode_config_file': '<(DEPTH)/JavaScriptCore/Configurations/JavaScriptCore.xcconfig', + 'xcode_config_file': '<(project_dir)/Configurations/JavaScriptCore.xcconfig', 'sources/': [ - ['exclude', 'qt'], - ['exclude', 'os-win32'], - ['exclude', 'wtf/android'], - ['exclude', 'wtf/brew'], - ['exclude', 'wtf/efl'], - ['exclude', 'wtf/gtk'], - ['exclude', 'wtf/qt'], - ['exclude', 'wtf/haiku'], - ['exclude', 'API/tests'], - ['exclude', 'wtf/url'], - ['exclude', 'wtf/wince'], - ['exclude', 'wtf/wx'], - ['exclude', 'wtf/unicode/brew'], - ['exclude', 'wtf/unicode/wince'], - ['exclude', 'wtf/unicode/glib'], - ['exclude', 'wtf/unicode/qt4'], + ['exclude', 'API/tests/'], + ['exclude', 'ForwardingHeaders/'], + ['exclude', '(?<!unicode)/icu/'], + ['exclude', 'os-win32/'], + ['exclude', 'qt/'], + ['exclude', 'wtf/(android|brew|efl|gtk|haiku|qt|wince|wx)/'], + ['exclude', 'wtf/unicode/brew/'], + ['exclude', 'wtf/unicode/glib/'], + ['exclude', 'wtf/unicode/qt4/'], + ['exclude', 'wtf/unicode/wince/'], + ['exclude', 'wtf/url/'], ['exclude', '/(gtk|glib|gobject)/.*\\.(cpp|h)$'], ['exclude', '(Default|Gtk|Chromium|None|Qt|Win|Wx|Symbian)\\.(cpp|mm|h)$'], - ['exclude', 'GCActivityCallback\.cpp'], - ['exclude', '.*BSTR.*$'], - ['exclude', 'jsc.cpp$'], + ['exclude', 'GCActivityCallback\.cpp$'], + ['exclude', 'BSTR[^/]*$'], ], 'postbuilds': [ { 'postbuild_name': 'Check For Global Initializers', 'action': [ - 'sh', '<(DEPTH)/gyp/run-if-exists.sh', '<(DEPTH)/../Tools/Scripts/check-for-global-initializers' + 'sh', '<(project_dir)/gyp/run-if-exists.sh', '<(DEPTH)/../Tools/Scripts/check-for-global-initializers' ], }, { 'postbuild_name': 'Check For Exit Time Destructors', 'action': [ - 'sh', '<(DEPTH)/gyp/run-if-exists.sh', '<(DEPTH)/../Tools/Scripts/check-for-exit-time-destructors' + 'sh', '<(project_dir)/gyp/run-if-exists.sh', '<(DEPTH)/../Tools/Scripts/check-for-exit-time-destructors' ], }, { 'postbuild_name': 'Check For Weak VTables and Externals', 'action': [ - 'sh', '<(DEPTH)/gyp/run-if-exists.sh', '<(DEPTH)/../Tools/Scripts/check-for-weak-vtables-and-externals' + 'sh', '<(project_dir)/gyp/run-if-exists.sh', '<(DEPTH)/../Tools/Scripts/check-for-weak-vtables-and-externals' ], }, ], @@ -103,29 +117,8 @@ 'xcode_settings': { # FIXME: Remove these overrides once JavaScriptCore.xcconfig is # used only by this project. - 'GCC_PREFIX_HEADER': '<(DEPTH)/JavaScriptCore/JavaScriptCorePrefix.h', - 'INFOPLIST_FILE': '<(DEPTH)/JavaScriptCore/Info.plist', - # This setting mirrors the setting in Base.xcconfig, with - # one difference noted below. - 'WARNING_CFLAGS_BASE': [ - '-Wall', - '-Wextra', - '-Wcast-qual', - '-Wchar-subscripts', - '-Wextra-tokens', - '-Wformat=2', - '-Winit-self', - # FIXME: For some reason, -Wmissing-format-attribute causes a - # build error in Assertions.cpp in the GYP build but not in the - # non-GYP build. - # '-Wmissing-format-attribute', - '-Wmissing-noreturn', - '-Wpacked', - '-Wpointer-arith', - '-Wredundant-decls', - '-Wundef', - '-Wwrite-strings', - ], + 'GCC_PREFIX_HEADER': '<(project_dir)/JavaScriptCorePrefix.h', + 'INFOPLIST_FILE': '<(project_dir)/Info.plist', }, }], ], @@ -133,14 +126,26 @@ { 'target_name': 'Derived Sources', 'type': 'none', - 'actions': [{ - 'action_name': 'Generate Derived Sources', - 'inputs': [], - 'outputs': [], - 'action': [ - 'sh', 'generate-derived-sources.sh', - ], - }], + 'actions': [ + { + 'action_name': 'Generate Derived Sources', + 'inputs': [], + 'outputs': [ + '<@(javascriptcore_derived_source_files)', + ], + 'action': [ + 'sh', 'generate-derived-sources.sh' + ], + }, + { + 'action_name': 'Generate DTrace Header', + 'inputs': [], + 'outputs': [], + 'action': [ + 'sh', '<(project_dir)/gyp/generate-dtrace-header.sh', '<(project_dir)' + ] + } + ], }, { 'target_name': 'Update Version', @@ -150,7 +155,7 @@ 'inputs': [], 'outputs': [], 'action': [ - 'sh', '<(DEPTH)/gyp/update-info-plist.sh', '<(DEPTH)/JavaScriptCore/Info.plist' + 'sh', '<(project_dir)/gyp/update-info-plist.sh', '<(project_dir)/Info.plist' ] }], }, @@ -206,10 +211,17 @@ 'include_dirs': [ '<@(javascriptcore_include_dirs)', ], + 'configurations': { + 'Production': { + 'xcode_settings': { + 'INSTALL_PATH': '$(JAVASCRIPTCORE_FRAMEWORKS_DIR)/JavaScriptCore.framework/Resources', + }, + }, + }, 'sources': [ '<@(jsc_files)', '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework', - 'libedit.dylib', + '/usr/lib/libedit.dylib', ], }, ], # targets diff --git a/Source/JavaScriptCore/gyp/generate-dtrace-header.sh b/Source/JavaScriptCore/gyp/generate-dtrace-header.sh new file mode 100755 index 0000000..a3c31dd --- /dev/null +++ b/Source/JavaScriptCore/gyp/generate-dtrace-header.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +TRACING_D="$1/runtime/Tracing.d"; +TRACING_H="$BUILT_PRODUCTS_DIR/DerivedSources/JavaScriptCore/TracingDtrace.h"; + +if [[ "${HAVE_DTRACE}" = "1" && "${TRACING_D}" -nt "${TRACING_H}" ]]; then + dtrace -h -o "${TRACING_H}" -s "${TRACING_D}"; +fi; + diff --git a/Source/JavaScriptCore/gyp/run-if-exists.sh b/Source/JavaScriptCore/gyp/run-if-exists.sh new file mode 100755 index 0000000..242ffc8 --- /dev/null +++ b/Source/JavaScriptCore/gyp/run-if-exists.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +if [ -f $1 ]; then + $1 || exit $?; +fi diff --git a/Source/JavaScriptCore/gyp/update-info-plist.sh b/Source/JavaScriptCore/gyp/update-info-plist.sh new file mode 100755 index 0000000..d02ecce --- /dev/null +++ b/Source/JavaScriptCore/gyp/update-info-plist.sh @@ -0,0 +1,4 @@ +# Touch Info.plist to let Xcode know it needs to copy it into the built product +if [[ "${CONFIGURATION}" != "Production" ]]; then + touch "$1"; +fi diff --git a/Source/JavaScriptCore/interpreter/CachedCall.h b/Source/JavaScriptCore/interpreter/CachedCall.h index 05e9056..04f2210 100644 --- a/Source/JavaScriptCore/interpreter/CachedCall.h +++ b/Source/JavaScriptCore/interpreter/CachedCall.h @@ -38,7 +38,7 @@ namespace JSC { CachedCall(CallFrame* callFrame, JSFunction* function, int argCount) : m_valid(false) , m_interpreter(callFrame->interpreter()) - , m_globalObjectScope(callFrame, function->scope()->globalObject.get()) + , m_globalObjectScope(callFrame->globalData(), function->scope()->globalObject.get()) { ASSERT(!function->isHostFunction()); m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, function, argCount, function->scope()); diff --git a/Source/JavaScriptCore/interpreter/CallFrame.h b/Source/JavaScriptCore/interpreter/CallFrame.h index e73e13a..28832e0 100644 --- a/Source/JavaScriptCore/interpreter/CallFrame.h +++ b/Source/JavaScriptCore/interpreter/CallFrame.h @@ -65,7 +65,7 @@ namespace JSC { // But they're used in many places in legacy code, so they're not going away any time soon. void clearException() { globalData().exception = JSValue(); } - JSValue exception() const { return globalData().exception.get(); } + JSValue exception() const { return globalData().exception; } bool hadException() const { return globalData().exception; } const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; } diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp index b9a9c40..6021279 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.cpp +++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp @@ -106,7 +106,7 @@ NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, J PropertySlot slot(o); if (o->getPropertySlot(callFrame, ident, slot)) { JSValue result = slot.getValue(callFrame, ident); - exceptionValue = callFrame->globalData().exception.get(); + exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; callFrame->uncheckedR(dst) = JSValue(result); @@ -145,7 +145,7 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP PropertySlot slot(o); if (o->getPropertySlot(callFrame, ident, slot)) { JSValue result = slot.getValue(callFrame, ident); - exceptionValue = callFrame->globalData().exception.get(); + exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; ASSERT(result); @@ -186,7 +186,7 @@ NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* return true; } - exceptionValue = callFrame->globalData().exception.get(); + exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; callFrame->uncheckedR(dst) = JSValue(result); @@ -226,7 +226,7 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru PropertySlot slot(o); if (o->getPropertySlot(callFrame, ident, slot)) { JSValue result = slot.getValue(callFrame, ident); - exceptionValue = callFrame->globalData().exception.get(); + exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; ASSERT(result); @@ -265,7 +265,7 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru return true; } - exceptionValue = callFrame->globalData().exception.get(); + exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; ASSERT(result); @@ -313,7 +313,7 @@ NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Inst PropertySlot slot(base); if (base->getPropertySlot(callFrame, ident, slot)) { JSValue result = slot.getValue(callFrame, ident); - exceptionValue = callFrame->globalData().exception.get(); + exceptionValue = callFrame->globalData().exception; if (exceptionValue) return false; callFrame->uncheckedR(propDst) = JSValue(result); @@ -409,13 +409,13 @@ NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* r ScopeChainNode* scopeChain = callFrame->scopeChain(); JSValue exceptionValue; - RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, codeBlock->isStrictMode(), programSource, scopeChain, exceptionValue); + EvalExecutable* eval = codeBlock->evalCodeCache().get(callFrame, codeBlock->ownerExecutable(), codeBlock->isStrictMode(), programSource, scopeChain, exceptionValue); ASSERT(!eval == exceptionValue); if (UNLIKELY(!eval)) return throwError(callFrame, exceptionValue); - return callFrame->globalData().interpreter->execute(eval.get(), callFrame, callFrame->uncheckedR(codeBlock->thisRegister()).jsValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain); + return callFrame->globalData().interpreter->execute(eval, callFrame, callFrame->uncheckedR(codeBlock->thisRegister()).jsValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain); } Interpreter::Interpreter(JSGlobalData& globalData) @@ -738,6 +738,8 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth) return checkedReturn(throwStackOverflowError(callFrame)); + DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get()); + JSObject* error = program->compile(callFrame, scopeChain); if (error) return checkedReturn(throwError(callFrame, error)); @@ -757,8 +759,6 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), codeBlock->m_numParameters, 0); newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = JSValue(thisObj); - DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject.get()); - Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) (*profiler)->willExecute(callFrame, program->sourceURL(), program->lineNo()); @@ -813,6 +813,8 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT if (callType == CallTypeJS) { ScopeChainNode* callDataScopeChain = callData.js.scopeChain; + DynamicGlobalObjectScope globalObjectScope(*callDataScopeChain->globalData, callDataScopeChain->globalObject.get()); + JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain); if (UNLIKELY(!!compileError)) { m_registerFile.shrink(oldEnd); @@ -828,8 +830,6 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT newCallFrame->init(newCodeBlock, 0, callDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, function); - DynamicGlobalObjectScope globalObjectScope(newCallFrame, callDataScopeChain->globalObject.get()); - Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) (*profiler)->willExecute(callFrame, function); @@ -860,7 +860,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset); newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, function); - DynamicGlobalObjectScope globalObjectScope(newCallFrame, scopeChain->globalObject.get()); + DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get()); Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) @@ -902,6 +902,8 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc if (constructType == ConstructTypeJS) { ScopeChainNode* constructDataScopeChain = constructData.js.scopeChain; + DynamicGlobalObjectScope globalObjectScope(*constructDataScopeChain->globalData, constructDataScopeChain->globalObject.get()); + JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, constructDataScopeChain); if (UNLIKELY(!!compileError)) { m_registerFile.shrink(oldEnd); @@ -917,8 +919,6 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc newCallFrame->init(newCodeBlock, 0, constructDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor); - DynamicGlobalObjectScope globalObjectScope(newCallFrame, constructDataScopeChain->globalObject.get()); - Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) (*profiler)->willExecute(callFrame, constructor); @@ -952,7 +952,7 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset); newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor); - DynamicGlobalObjectScope globalObjectScope(newCallFrame, scopeChain->globalObject.get()); + DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get()); Profiler** profiler = Profiler::enabledProfilerReference(); if (*profiler) @@ -1066,11 +1066,11 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec { ASSERT(!scopeChain->globalData->exception); + DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get()); + if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth) return checkedReturn(throwStackOverflowError(callFrame)); - DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject.get()); - JSObject* compileError = eval->compile(callFrame, scopeChain); if (UNLIKELY(!!compileError)) return checkedReturn(throwError(callFrame, compileError)); @@ -1467,8 +1467,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #define CHECK_FOR_EXCEPTION() \ do { \ - if (UNLIKELY(globalData->exception.get() != JSValue())) { \ - exceptionValue = globalData->exception.get(); \ + if (UNLIKELY(globalData->exception != JSValue())) { \ + exceptionValue = globalData->exception; \ goto vm_throw; \ } \ } while (0) @@ -1549,8 +1549,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi register dst. */ int dst = vPC[1].u.operand; - int regExp = vPC[2].u.operand; - callFrame->uncheckedR(dst) = JSValue(new (globalData) RegExpObject(callFrame->lexicalGlobalObject(), callFrame->scopeChain()->globalObject->regExpStructure(), codeBlock->regexp(regExp))); + RegExp* regExp = codeBlock->regexp(vPC[2].u.operand); + if (!regExp->isValid()) { + exceptionValue = createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor."); + goto vm_throw; + } + callFrame->uncheckedR(dst) = JSValue(new (globalData) RegExpObject(callFrame->lexicalGlobalObject(), callFrame->scopeChain()->globalObject->regExpStructure(), regExp)); vPC += OPCODE_LENGTH(op_new_regexp); NEXT_INSTRUCTION(); @@ -3533,10 +3537,9 @@ skip_id_custom_self: to ptr, using pointer equality. */ int src = vPC[1].u.operand; - JSValue ptr = JSValue(vPC[2].u.jsCell); int target = vPC[3].u.operand; JSValue srcValue = callFrame->r(src).jsValue(); - if (srcValue != ptr) { + if (srcValue != vPC[2].u.jsCell.get()) { vPC += target; NEXT_INSTRUCTION(); } @@ -3831,7 +3834,7 @@ skip_id_custom_self: if (thisValue == globalObject && funcVal == globalObject->evalFunction()) { JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset); - if ((exceptionValue = globalData->exception.get())) + if ((exceptionValue = globalData->exception)) goto vm_throw; functionReturnValue = result; @@ -4261,7 +4264,7 @@ skip_id_custom_self: Structure* structure; JSValue proto = callFrame->r(protoRegister).jsValue(); if (proto.isObject()) - structure = asObject(proto)->inheritorID(); + structure = asObject(proto)->inheritorID(callFrame->globalData()); else structure = constructor->scope()->globalObject->emptyObjectStructure(); callFrame->uncheckedR(thisRegister) = constructEmptyObject(callFrame, structure); diff --git a/Source/JavaScriptCore/interpreter/Register.h b/Source/JavaScriptCore/interpreter/Register.h index 3944642..fb02c12 100644 --- a/Source/JavaScriptCore/interpreter/Register.h +++ b/Source/JavaScriptCore/interpreter/Register.h @@ -54,11 +54,10 @@ namespace JSC { Register(const JSValue&); Register& operator=(const JSValue&); JSValue jsValue() const; + EncodedJSValue encodedJSValue() const; - Register& operator=(JSActivation*); Register& operator=(CallFrame*); Register& operator=(CodeBlock*); - Register& operator=(JSPropertyNameIterator*); Register& operator=(ScopeChainNode*); Register& operator=(Instruction*); @@ -73,29 +72,17 @@ namespace JSC { static Register withInt(int32_t i) { - Register r; - r.u.i = i; + Register r = jsNumber(i); return r; } - static Register withCallee(JSObject* callee) - { - Register r; - r.u.function = callee; - return r; - } + static inline Register withCallee(JSObject* callee); private: union { - int32_t i; EncodedJSValue value; - - JSActivation* activation; CallFrame* callFrame; CodeBlock* codeBlock; - JSObject* function; - JSPropertyNameIterator* propertyNameIterator; - ScopeChainNode* scopeChain; Instruction* vPC; } u; }; @@ -129,14 +116,13 @@ namespace JSC { return JSValue::decode(u.value); } - // Interpreter functions - - ALWAYS_INLINE Register& Register::operator=(JSActivation* activation) + ALWAYS_INLINE EncodedJSValue Register::encodedJSValue() const { - u.activation = activation; - return *this; + return u.value; } + // Interpreter functions + ALWAYS_INLINE Register& Register::operator=(CallFrame* callFrame) { u.callFrame = callFrame; @@ -155,28 +141,11 @@ namespace JSC { return *this; } - ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain) - { - u.scopeChain = scopeChain; - return *this; - } - - ALWAYS_INLINE Register& Register::operator=(JSPropertyNameIterator* propertyNameIterator) - { - u.propertyNameIterator = propertyNameIterator; - return *this; - } - ALWAYS_INLINE int32_t Register::i() const { - return u.i; + return jsValue().asInt32(); } - - ALWAYS_INLINE JSActivation* Register::activation() const - { - return u.activation; - } - + ALWAYS_INLINE CallFrame* Register::callFrame() const { return u.callFrame; @@ -186,22 +155,7 @@ namespace JSC { { return u.codeBlock; } - - ALWAYS_INLINE JSObject* Register::function() const - { - return u.function; - } - - ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const - { - return u.propertyNameIterator; - } - - ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const - { - return u.scopeChain; - } - + ALWAYS_INLINE Instruction* Register::vPC() const { return u.vPC; diff --git a/Source/JavaScriptCore/interpreter/RegisterFile.cpp b/Source/JavaScriptCore/interpreter/RegisterFile.cpp index 47f0c18..b3a87e5 100644 --- a/Source/JavaScriptCore/interpreter/RegisterFile.cpp +++ b/Source/JavaScriptCore/interpreter/RegisterFile.cpp @@ -29,6 +29,7 @@ #include "config.h" #include "RegisterFile.h" +#include "ConservativeSet.h" #include "Interpreter.h" #include "JSGlobalData.h" #include "JSGlobalObject.h" @@ -51,6 +52,16 @@ RegisterFile::~RegisterFile() m_reservation.deallocate(); } +void RegisterFile::gatherConservativeRoots(ConservativeRoots& conservativeRoots) +{ + for (Register* it = start(); it != end(); ++it) { + JSValue v = it->jsValue(); + if (!v.isCell()) + continue; + conservativeRoots.add(v.asCell()); + } +} + void RegisterFile::releaseExcessCapacity() { m_reservation.decommit(m_start, reinterpret_cast<intptr_t>(m_commitEnd) - reinterpret_cast<intptr_t>(m_start)); diff --git a/Source/JavaScriptCore/interpreter/RegisterFile.h b/Source/JavaScriptCore/interpreter/RegisterFile.h index bb42902..4d04085 100644 --- a/Source/JavaScriptCore/interpreter/RegisterFile.h +++ b/Source/JavaScriptCore/interpreter/RegisterFile.h @@ -91,7 +91,6 @@ namespace JSC { class RegisterFile { WTF_MAKE_NONCOPYABLE(RegisterFile); - friend class JIT; public: enum CallFrameHeaderEntry { CallFrameHeaderSize = 6, @@ -114,6 +113,8 @@ namespace JSC { RegisterFile(JSGlobalData&, size_t capacity = defaultCapacity, size_t maxGlobals = defaultMaxGlobals); ~RegisterFile(); + + void gatherConservativeRoots(ConservativeRoots&); Register* start() const { return m_start; } Register* end() const { return m_end; } @@ -136,6 +137,11 @@ namespace JSC { static Finalizer* globalObjectCollectedNotifier(); + Register* const * addressOfEnd() const + { + return &m_end; + } + private: void releaseExcessCapacity(); void addToCommittedByteCount(long); diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp index 29e3778..063ae8c 100644 --- a/Source/JavaScriptCore/jit/JIT.cpp +++ b/Source/JavaScriptCore/jit/JIT.cpp @@ -92,7 +92,7 @@ JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock, void* linkerOffset) #if USE(JSVALUE32_64) void JIT::emitTimeoutCheck() { - Jump skipTimeout = branchSub32(NonZero, Imm32(1), timeoutCheckRegister); + Jump skipTimeout = branchSub32(NonZero, TrustedImm32(1), timeoutCheckRegister); JITStubCall stubCall(this, cti_timeout_check); stubCall.addArgument(regT1, regT0); // save last result registers. stubCall.call(timeoutCheckRegister); @@ -102,7 +102,7 @@ void JIT::emitTimeoutCheck() #else void JIT::emitTimeoutCheck() { - Jump skipTimeout = branchSub32(NonZero, Imm32(1), timeoutCheckRegister); + Jump skipTimeout = branchSub32(NonZero, TrustedImm32(1), timeoutCheckRegister); JITStubCall(this, cti_timeout_check).call(timeoutCheckRegister); skipTimeout.link(this); @@ -475,7 +475,7 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck) emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock); addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), callFrameRegister, regT1); - registerFileCheck = branchPtr(Below, AbsoluteAddress(&m_globalData->interpreter->registerFile().m_end), regT1); + registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT1); } Label functionBody = label(); @@ -497,7 +497,7 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck) arityCheck = label(); preserveReturnAddressAfterCall(regT2); emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC); - branch32(Equal, regT1, Imm32(m_codeBlock->m_numParameters)).linkTo(beginLabel, this); + branch32(Equal, regT1, TrustedImm32(m_codeBlock->m_numParameters)).linkTo(beginLabel, this); restoreArgumentReference(); JITStubCall(this, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck).call(callFrameRegister); @@ -567,7 +567,6 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck) #if ENABLE(JIT_OPTIMIZE_CALL) for (unsigned i = 0; i < m_codeBlock->numberOfCallLinkInfos(); ++i) { CallLinkInfo& info = m_codeBlock->callLinkInfo(i); - info.ownerCodeBlock = m_codeBlock; info.callReturnLocation = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].callReturnLocation); info.hotPathBegin = patchBuffer.locationOf(m_callStructureStubCompilationInfo[i].hotPathBegin); info.hotPathOther = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].hotPathOther); @@ -588,18 +587,6 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck) } #if ENABLE(JIT_OPTIMIZE_CALL) -void JIT::unlinkCallOrConstruct(CallLinkInfo* callLinkInfo) -{ - // When the JSFunction is deleted the pointer embedded in the instruction stream will no longer be valid - // (and, if a new JSFunction happened to be constructed at the same location, we could get a false positive - // match). Reset the check so it no longer matches. - RepatchBuffer repatchBuffer(callLinkInfo->ownerCodeBlock); -#if USE(JSVALUE32_64) - repatchBuffer.repatch(callLinkInfo->hotPathBegin, 0); -#else - repatchBuffer.repatch(callLinkInfo->hotPathBegin, JSValue::encode(JSValue())); -#endif -} void JIT::linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JIT::CodePtr code, CallLinkInfo* callLinkInfo, int callerArgCount, JSGlobalData* globalData) { @@ -609,10 +596,7 @@ void JIT::linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* ca // If this is a native call calleeCodeBlock is null so the number of parameters is unimportant if (!calleeCodeBlock || (callerArgCount == calleeCodeBlock->m_numParameters)) { ASSERT(!callLinkInfo->isLinked()); - - if (calleeCodeBlock) - calleeCodeBlock->addCaller(callLinkInfo); - + callLinkInfo->callee.set(*globalData, callerCodeBlock->ownerExecutable(), callee); repatchBuffer.repatch(callLinkInfo->hotPathBegin, callee); repatchBuffer.relink(callLinkInfo->hotPathOther, code); } @@ -629,10 +613,7 @@ void JIT::linkConstruct(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBloc // If this is a native call calleeCodeBlock is null so the number of parameters is unimportant if (!calleeCodeBlock || (callerArgCount == calleeCodeBlock->m_numParameters)) { ASSERT(!callLinkInfo->isLinked()); - - if (calleeCodeBlock) - calleeCodeBlock->addCaller(callLinkInfo); - + callLinkInfo->callee.set(*globalData, callerCodeBlock->ownerExecutable(), callee); repatchBuffer.repatch(callLinkInfo->hotPathBegin, callee); repatchBuffer.relink(callLinkInfo->hotPathOther, code); } diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h index f98158c..61bd2ab 100644 --- a/Source/JavaScriptCore/jit/JIT.h +++ b/Source/JavaScriptCore/jit/JIT.h @@ -245,7 +245,6 @@ namespace JSC { static void linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, CodePtr, CallLinkInfo*, int callerArgCount, JSGlobalData*); static void linkConstruct(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, CodePtr, CallLinkInfo*, int callerArgCount, JSGlobalData*); - static void unlinkCallOrConstruct(CallLinkInfo*); private: struct JSRInfo { @@ -310,7 +309,7 @@ namespace JSC { void emitStore(unsigned index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister); void emitStore(unsigned index, const JSValue constant, RegisterID base = callFrameRegister); void emitStoreInt32(unsigned index, RegisterID payload, bool indexIsInt32 = false); - void emitStoreInt32(unsigned index, Imm32 payload, bool indexIsInt32 = false); + void emitStoreInt32(unsigned index, TrustedImm32 payload, bool indexIsInt32 = false); void emitStoreCell(unsigned index, RegisterID payload, bool indexIsCell = false); void emitStoreBool(unsigned index, RegisterID tag, bool indexIsBool = false); void emitStoreDouble(unsigned index, FPRegisterID value); @@ -854,6 +853,8 @@ namespace JSC { void emitInitRegister(unsigned dst); void emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry); + void emitPutCellToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry); + void emitPutIntToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry); void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry); void emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from = callFrameRegister); void emitGetFromCallFrameHeader32(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from = callFrameRegister); diff --git a/Source/JavaScriptCore/jit/JITArithmetic.cpp b/Source/JavaScriptCore/jit/JITArithmetic.cpp index cd05f51..edf2290 100644 --- a/Source/JavaScriptCore/jit/JITArithmetic.cpp +++ b/Source/JavaScriptCore/jit/JITArithmetic.cpp @@ -167,7 +167,7 @@ void JIT::emit_op_urshift(Instruction* currentInstruction) // a toUint conversion, which can result in a value we can represent // as an immediate int. if (shift < 0 || !(shift & 31)) - addSlowCase(branch32(LessThan, regT0, Imm32(0))); + addSlowCase(branch32(LessThan, regT0, TrustedImm32(0))); emitFastArithReTagImmediate(regT0, regT0); emitPutVirtualRegister(dst, regT0); return; @@ -179,7 +179,7 @@ void JIT::emit_op_urshift(Instruction* currentInstruction) emitFastArithImmToInt(regT0); emitFastArithImmToInt(regT1); urshift32(regT1, regT0); - addSlowCase(branch32(LessThan, regT0, Imm32(0))); + addSlowCase(branch32(LessThan, regT0, TrustedImm32(0))); emitFastArithReTagImmediate(regT0, regT0); emitPutVirtualRegister(dst, regT0); } @@ -202,7 +202,7 @@ void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEn if (shift) urshift32(Imm32(shift & 0x1f), regT0); if (shift < 0 || !(shift & 31)) - failures.append(branch32(LessThan, regT0, Imm32(0))); + failures.append(branch32(LessThan, regT0, TrustedImm32(0))); emitFastArithReTagImmediate(regT0, regT0); emitPutVirtualRegister(dst, regT0); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift)); @@ -224,7 +224,7 @@ void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEn failures.append(emitJumpIfNotImmediateInteger(regT1)); // op2 is not an int emitFastArithImmToInt(regT1); urshift32(regT1, regT0); - failures.append(branch32(LessThan, regT0, Imm32(0))); + failures.append(branch32(LessThan, regT0, TrustedImm32(0))); emitFastArithReTagImmediate(regT0, regT0); emitPutVirtualRegister(dst, regT0); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift)); @@ -773,7 +773,7 @@ void JIT::emit_op_post_inc(Instruction* currentInstruction) emitGetVirtualRegister(srcDst, regT0); move(regT0, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT0); - addSlowCase(branchAdd32(Overflow, Imm32(1), regT1)); + addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT1)); emitFastArithIntToImmNoCheck(regT1, regT1); emitPutVirtualRegister(srcDst, regT1); emitPutVirtualRegister(result); @@ -800,7 +800,7 @@ void JIT::emit_op_post_dec(Instruction* currentInstruction) emitGetVirtualRegister(srcDst, regT0); move(regT0, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT0); - addSlowCase(branchSub32(Zero, Imm32(1), regT1)); + addSlowCase(branchSub32(Zero, TrustedImm32(1), regT1)); emitFastArithIntToImmNoCheck(regT1, regT1); emitPutVirtualRegister(srcDst, regT1); emitPutVirtualRegister(result); @@ -825,7 +825,7 @@ void JIT::emit_op_pre_inc(Instruction* currentInstruction) emitGetVirtualRegister(srcDst, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); - addSlowCase(branchAdd32(Overflow, Imm32(1), regT0)); + addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0)); emitFastArithIntToImmNoCheck(regT0, regT0); emitPutVirtualRegister(srcDst); } @@ -849,7 +849,7 @@ void JIT::emit_op_pre_dec(Instruction* currentInstruction) emitGetVirtualRegister(srcDst, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); - addSlowCase(branchSub32(Zero, Imm32(1), regT0)); + addSlowCase(branchSub32(Zero, TrustedImm32(1), regT0)); emitFastArithIntToImmNoCheck(regT0, regT0); emitPutVirtualRegister(srcDst); } @@ -888,7 +888,7 @@ void JIT::emit_op_mod(Instruction* currentInstruction) emitJumpSlowCaseIfNotImmediateInteger(regT0); emitJumpSlowCaseIfNotImmediateInteger(regT2); - addSlowCase(branchPtr(Equal, regT2, ImmPtr(JSValue::encode(jsNumber(0))))); + addSlowCase(branchPtr(Equal, regT2, TrustedImmPtr(JSValue::encode(jsNumber(0))))); m_assembler.cdq(); m_assembler.idivl_r(regT2); emitFastArithReTagImmediate(regT1, regT0); diff --git a/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp b/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp index e0b31f0..6865489 100644 --- a/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp +++ b/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp @@ -54,17 +54,17 @@ void JIT::emit_op_negate(Instruction* currentInstruction) emitLoad(src, regT1, regT0); - Jump srcNotInt = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); - addSlowCase(branchTest32(Zero, regT0, Imm32(0x7fffffff))); + Jump srcNotInt = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)); + addSlowCase(branchTest32(Zero, regT0, TrustedImm32(0x7fffffff))); neg32(regT0); emitStoreInt32(dst, regT0, (dst == src)); Jump end = jump(); srcNotInt.link(this); - addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); + addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag))); - xor32(Imm32(1 << 31), regT1); + xor32(TrustedImm32(1 << 31), regT1); store32(regT1, tagFor(dst)); if (dst != src) store32(regT0, payloadFor(dst)); @@ -96,7 +96,7 @@ void JIT::emit_op_jnless(Instruction* currentInstruction) // Character less. if (isOperandConstantImmediateChar(op1)) { emitLoad(op2, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag))); JumpList failures; emitLoadCharacterString(regT0, regT0, failures); addSlowCase(failures); @@ -105,7 +105,7 @@ void JIT::emit_op_jnless(Instruction* currentInstruction) } if (isOperandConstantImmediateChar(op2)) { emitLoad(op1, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag))); JumpList failures; emitLoadCharacterString(regT0, regT0, failures); addSlowCase(failures); @@ -115,16 +115,16 @@ void JIT::emit_op_jnless(Instruction* currentInstruction) if (isOperandConstantImmediateInt(op1)) { // Int32 less. emitLoad(op2, regT3, regT2); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); addJump(branch32(LessThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target); } else if (isOperandConstantImmediateInt(op2)) { emitLoad(op1, regT1, regT0); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target); } else { emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); addJump(branch32(GreaterThanOrEqual, regT0, regT2), target); } @@ -185,7 +185,7 @@ void JIT::emit_op_jless(Instruction* currentInstruction) // Character less. if (isOperandConstantImmediateChar(op1)) { emitLoad(op2, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag))); JumpList failures; emitLoadCharacterString(regT0, regT0, failures); addSlowCase(failures); @@ -194,7 +194,7 @@ void JIT::emit_op_jless(Instruction* currentInstruction) } if (isOperandConstantImmediateChar(op2)) { emitLoad(op1, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag))); JumpList failures; emitLoadCharacterString(regT0, regT0, failures); addSlowCase(failures); @@ -203,16 +203,16 @@ void JIT::emit_op_jless(Instruction* currentInstruction) } if (isOperandConstantImmediateInt(op1)) { emitLoad(op2, regT3, regT2); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); addJump(branch32(GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target); } else if (isOperandConstantImmediateInt(op2)) { emitLoad(op1, regT1, regT0); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target); } else { emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); addJump(branch32(LessThan, regT0, regT2), target); } @@ -272,7 +272,7 @@ void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert) // Character less. if (isOperandConstantImmediateChar(op1)) { emitLoad(op2, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag))); JumpList failures; emitLoadCharacterString(regT0, regT0, failures); addSlowCase(failures); @@ -281,7 +281,7 @@ void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert) } if (isOperandConstantImmediateChar(op2)) { emitLoad(op1, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag))); JumpList failures; emitLoadCharacterString(regT0, regT0, failures); addSlowCase(failures); @@ -290,16 +290,16 @@ void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert) } if (isOperandConstantImmediateInt(op1)) { emitLoad(op2, regT3, regT2); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target); } else if (isOperandConstantImmediateInt(op2)) { emitLoad(op1, regT1, regT0); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target); } else { emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, regT2), target); } @@ -368,7 +368,7 @@ void JIT::emit_op_lshift(Instruction* currentInstruction) if (isOperandConstantImmediateInt(op2)) { emitLoad(op1, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); lshift32(Imm32(getConstantOperand(op2).asInt32()), regT0); emitStoreInt32(dst, regT0, dst == op1); return; @@ -376,8 +376,8 @@ void JIT::emit_op_lshift(Instruction* currentInstruction) emitLoad2(op1, regT1, regT0, op2, regT3, regT2); if (!isOperandConstantImmediateInt(op1)) - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); lshift32(regT2, regT0); emitStoreInt32(dst, regT0, dst == op1 || dst == op2); } @@ -410,7 +410,7 @@ void JIT::emitRightShift(Instruction* currentInstruction, bool isUnsigned) // shift arguments, so any changes must be updated there as well. if (isOperandConstantImmediateInt(op2)) { emitLoad(op1, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); int shift = getConstantOperand(op2).asInt32(); if (isUnsigned) { if (shift) @@ -419,7 +419,7 @@ void JIT::emitRightShift(Instruction* currentInstruction, bool isUnsigned) // a toUint conversion, which can result in a value we can represent // as an immediate int. if (shift < 0 || !(shift & 31)) - addSlowCase(branch32(LessThan, regT0, Imm32(0))); + addSlowCase(branch32(LessThan, regT0, TrustedImm32(0))); } else if (shift) { // signed right shift by zero is simply toInt conversion rshift32(Imm32(shift & 0x1f), regT0); } @@ -429,11 +429,11 @@ void JIT::emitRightShift(Instruction* currentInstruction, bool isUnsigned) emitLoad2(op1, regT1, regT0, op2, regT3, regT2); if (!isOperandConstantImmediateInt(op1)) - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); if (isUnsigned) { urshift32(regT2, regT0); - addSlowCase(branch32(LessThan, regT0, Imm32(0))); + addSlowCase(branch32(LessThan, regT0, TrustedImm32(0))); } else rshift32(regT2, regT0); emitStoreInt32(dst, regT0, dst == op1 || dst == op2); @@ -450,14 +450,14 @@ void JIT::emitRightShiftSlowCase(Instruction* currentInstruction, Vector<SlowCas linkSlowCase(iter); // int32 check if (supportsFloatingPointTruncate()) { JumpList failures; - failures.append(branch32(AboveOrEqual, regT1, Imm32(JSValue::LowestTag))); + failures.append(branch32(AboveOrEqual, regT1, TrustedImm32(JSValue::LowestTag))); emitLoadDouble(op1, fpRegT0); failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0)); if (isUnsigned) { if (shift) urshift32(Imm32(shift & 0x1f), regT0); if (shift < 0 || !(shift & 31)) - failures.append(branch32(LessThan, regT0, Imm32(0))); + failures.append(branch32(LessThan, regT0, TrustedImm32(0))); } else if (shift) rshift32(Imm32(shift & 0x1f), regT0); emitStoreInt32(dst, regT0, false); @@ -472,9 +472,9 @@ void JIT::emitRightShiftSlowCase(Instruction* currentInstruction, Vector<SlowCas if (!isOperandConstantImmediateInt(op1)) { linkSlowCase(iter); // int32 check -- op1 is not an int if (supportsFloatingPointTruncate()) { - Jump notDouble = branch32(Above, regT1, Imm32(JSValue::LowestTag)); // op1 is not a double + Jump notDouble = branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)); // op1 is not a double emitLoadDouble(op1, fpRegT0); - Jump notInt = branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)); // op2 is not an int + Jump notInt = branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)); // op2 is not an int Jump cantTruncate = branchTruncateDoubleToInt32(fpRegT0, regT0); if (isUnsigned) urshift32(regT2, regT0); @@ -535,15 +535,15 @@ void JIT::emit_op_bitand(Instruction* currentInstruction) int32_t constant; if (getOperandConstantImmediateInt(op1, op2, op, constant)) { emitLoad(op, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); and32(Imm32(constant), regT0); emitStoreInt32(dst, regT0, (op == dst)); return; } emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); and32(regT2, regT0); emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); } @@ -576,15 +576,15 @@ void JIT::emit_op_bitor(Instruction* currentInstruction) int32_t constant; if (getOperandConstantImmediateInt(op1, op2, op, constant)) { emitLoad(op, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); or32(Imm32(constant), regT0); emitStoreInt32(dst, regT0, (op == dst)); return; } emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); or32(regT2, regT0); emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); } @@ -617,15 +617,15 @@ void JIT::emit_op_bitxor(Instruction* currentInstruction) int32_t constant; if (getOperandConstantImmediateInt(op1, op2, op, constant)) { emitLoad(op, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); xor32(Imm32(constant), regT0); emitStoreInt32(dst, regT0, (op == dst)); return; } emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); xor32(regT2, regT0); emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); } @@ -654,7 +654,7 @@ void JIT::emit_op_bitnot(Instruction* currentInstruction) unsigned src = currentInstruction[2].u.operand; emitLoad(src, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); not32(regT0); emitStoreInt32(dst, regT0, (dst == src)); @@ -679,14 +679,14 @@ void JIT::emit_op_post_inc(Instruction* currentInstruction) unsigned srcDst = currentInstruction[2].u.operand; emitLoad(srcDst, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); if (dst == srcDst) // x = x++ is a noop for ints. return; emitStoreInt32(dst, regT0); - addSlowCase(branchAdd32(Overflow, Imm32(1), regT0)); + addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0)); emitStoreInt32(srcDst, regT0, true); } @@ -713,14 +713,14 @@ void JIT::emit_op_post_dec(Instruction* currentInstruction) unsigned srcDst = currentInstruction[2].u.operand; emitLoad(srcDst, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); if (dst == srcDst) // x = x-- is a noop for ints. return; emitStoreInt32(dst, regT0); - addSlowCase(branchSub32(Overflow, Imm32(1), regT0)); + addSlowCase(branchSub32(Overflow, TrustedImm32(1), regT0)); emitStoreInt32(srcDst, regT0, true); } @@ -735,7 +735,7 @@ void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseE JITStubCall stubCall(this, cti_op_post_dec); stubCall.addArgument(srcDst); - stubCall.addArgument(Imm32(srcDst)); + stubCall.addArgument(TrustedImm32(srcDst)); stubCall.call(dst); } @@ -747,8 +747,8 @@ void JIT::emit_op_pre_inc(Instruction* currentInstruction) emitLoad(srcDst, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branchAdd32(Overflow, Imm32(1), regT0)); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0)); emitStoreInt32(srcDst, regT0, true); } @@ -772,8 +772,8 @@ void JIT::emit_op_pre_dec(Instruction* currentInstruction) emitLoad(srcDst, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branchSub32(Overflow, Imm32(1), regT0)); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + addSlowCase(branchSub32(Overflow, TrustedImm32(1), regT0)); emitStoreInt32(srcDst, regT0, true); } @@ -817,8 +817,8 @@ void JIT::emit_op_add(Instruction* currentInstruction) } emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); // Int32 case. addSlowCase(branchAdd32(Overflow, regT2, regT0)); @@ -840,7 +840,7 @@ void JIT::emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultT { // Int32 case. emitLoad(op, regT1, regT0); - Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); + Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)); addSlowCase(branchAdd32(Overflow, Imm32(constant), regT0)); emitStoreInt32(dst, regT0, (op == dst)); @@ -853,7 +853,7 @@ void JIT::emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultT notInt32.link(this); if (!opType.definitelyIsNumber()) - addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); + addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag))); move(Imm32(constant), regT2); convertInt32ToDouble(regT2, fpRegT0); emitLoadDouble(op, fpRegT1); @@ -926,8 +926,8 @@ void JIT::emit_op_sub(Instruction* currentInstruction) } emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); // Int32 case. addSlowCase(branchSub32(Overflow, regT2, regT0)); @@ -949,7 +949,7 @@ void JIT::emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultT { // Int32 case. emitLoad(op, regT1, regT0); - Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); + Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)); addSlowCase(branchSub32(Overflow, Imm32(constant), regT0)); emitStoreInt32(dst, regT0, (op == dst)); @@ -962,7 +962,7 @@ void JIT::emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultT notInt32.link(this); if (!opType.definitelyIsNumber()) - addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); + addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag))); move(Imm32(constant), regT2); convertInt32ToDouble(regT2, fpRegT0); emitLoadDouble(op, fpRegT1); @@ -1019,15 +1019,15 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi // Verify Op1 is double. if (!types.first().definitelyIsNumber()) - addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); + addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag))); if (!op2IsInRegisters) emitLoad(op2, regT3, regT2); - Jump doubleOp2 = branch32(Below, regT3, Imm32(JSValue::LowestTag)); + Jump doubleOp2 = branch32(Below, regT3, TrustedImm32(JSValue::LowestTag)); if (!types.second().definitelyIsNumber()) - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); convertInt32ToDouble(regT2, fpRegT0); Jump doTheMath = jump(); @@ -1096,7 +1096,7 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi // Verify op2 is double. if (!types.second().definitelyIsNumber()) - addSlowCase(branch32(Above, regT3, Imm32(JSValue::LowestTag))); + addSlowCase(branch32(Above, regT3, TrustedImm32(JSValue::LowestTag))); // Do the math. switch (opcodeID) { @@ -1157,8 +1157,8 @@ void JIT::emit_op_mul(Instruction* currentInstruction) JumpList notInt32Op2; emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); // Int32 case. move(regT0, regT3); @@ -1189,7 +1189,7 @@ void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry> linkSlowCase(iter); // zero result check Jump negZero = branchOr32(Signed, regT2, regT3); - emitStoreInt32(dst, Imm32(0), (op1 == dst || op2 == dst)); + emitStoreInt32(dst, TrustedImm32(0), (op1 == dst || op2 == dst)); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul)); @@ -1240,8 +1240,8 @@ void JIT::emit_op_div(Instruction* currentInstruction) emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); convertInt32ToDouble(regT0, fpRegT0); convertInt32ToDouble(regT2, fpRegT1); @@ -1312,16 +1312,16 @@ void JIT::emit_op_mod(Instruction* currentInstruction) if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) { emitLoad(op1, regT1, regT0); move(Imm32(getConstantOperand(op2).asInt32()), regT2); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); if (getConstantOperand(op2).asInt32() == -1) - addSlowCase(branch32(Equal, regT0, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC + addSlowCase(branch32(Equal, regT0, TrustedImm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC } else { emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); - addSlowCase(branch32(Equal, regT0, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC - addSlowCase(branch32(Equal, regT2, Imm32(0))); // divide by 0 + addSlowCase(branch32(Equal, regT0, TrustedImm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC + addSlowCase(branch32(Equal, regT2, TrustedImm32(0))); // divide by 0 } move(regT0, regT3); // Save dividend payload, in case of 0. @@ -1335,7 +1335,7 @@ void JIT::emit_op_mod(Instruction* currentInstruction) // If the remainder is zero and the dividend is negative, the result is -0. Jump storeResult1 = branchTest32(NonZero, regT1); - Jump storeResult2 = branchTest32(Zero, regT3, Imm32(0x80000000)); // not negative + Jump storeResult2 = branchTest32(Zero, regT3, TrustedImm32(0x80000000)); // not negative emitStore(dst, jsNumber(-0.0)); Jump end = jump(); @@ -1378,10 +1378,10 @@ void JIT::emit_op_mod(Instruction* currentInstruction) #if ENABLE(JIT_USE_SOFT_MODULO) emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); - addSlowCase(branch32(Equal, regT2, Imm32(0))); + addSlowCase(branch32(Equal, regT2, TrustedImm32(0))); emitNakedCall(m_globalData->jitStubs->ctiSoftModulo()); diff --git a/Source/JavaScriptCore/jit/JITCall.cpp b/Source/JavaScriptCore/jit/JITCall.cpp index 524e576..77c2a69 100644 --- a/Source/JavaScriptCore/jit/JITCall.cpp +++ b/Source/JavaScriptCore/jit/JITCall.cpp @@ -48,10 +48,11 @@ namespace JSC { void JIT::compileOpCallInitializeCallFrame() { - store32(regT1, Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)))); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT3); // newScopeChain - storePtr(regT0, Address(callFrameRegister, RegisterFile::Callee * static_cast<int>(sizeof(Register)))); - storePtr(regT3, Address(callFrameRegister, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register)))); + // regT0 holds callee, regT1 holds argCount + loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT3); // scopeChain + emitPutIntToCallFrameHeader(regT1, RegisterFile::ArgumentCount); + emitPutCellToCallFrameHeader(regT0, RegisterFile::Callee); + emitPutCellToCallFrameHeader(regT3, RegisterFile::ScopeChain); } void JIT::emit_op_call_put_result(Instruction* instruction) @@ -67,15 +68,16 @@ void JIT::compileOpCallVarargs(Instruction* instruction) int registerOffset = instruction[3].u.operand; emitGetVirtualRegister(argCountRegister, regT1); + emitFastArithImmToInt(regT1); emitGetVirtualRegister(callee, regT0); addPtr(Imm32(registerOffset), regT1, regT2); // Check for JSFunctions. emitJumpSlowCaseIfNotJSCell(regT0); - addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr))); + addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr))); // Speculatively roll the callframe, assuming argCount will match the arity. - mul32(Imm32(sizeof(Register)), regT2, regT2); + mul32(TrustedImm32(sizeof(Register)), regT2, regT2); intptr_t offset = (intptr_t)sizeof(Register) * (intptr_t)RegisterFile::CallerFrame; addPtr(Imm32((int32_t)offset), regT2, regT3); addPtr(callFrameRegister, regT3); @@ -118,14 +120,14 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned) stubCall.addArgument(JIT::Imm32(registerOffset)); stubCall.addArgument(JIT::Imm32(argCount)); stubCall.call(); - wasEval = branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue()))); + wasEval = branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue()))); } emitGetVirtualRegister(callee, regT0); // Check for JSFunctions. emitJumpSlowCaseIfNotJSCell(regT0); - addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr))); + addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr))); // Speculatively roll the callframe, assuming argCount will match the arity. storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)))); @@ -175,7 +177,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca stubCall.addArgument(JIT::Imm32(registerOffset)); stubCall.addArgument(JIT::Imm32(argCount)); stubCall.call(); - wasEval = branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue()))); + wasEval = branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue()))); } // This plants a check for a cached JSFunction value, so we can plant a fast link to the callee. @@ -185,7 +187,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall); - Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, ImmPtr(JSValue::encode(JSValue()))); + Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(JSValue::encode(JSValue()))); END_UNINTERRUPTED_SEQUENCE(sequenceOpCall); @@ -199,8 +201,9 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca // Note that this omits to set up RegisterFile::CodeBlock, which is set in the callee loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1); // newScopeChain - - store32(Imm32(argCount), Address(callFrameRegister, (registerOffset + RegisterFile::ArgumentCount) * static_cast<int>(sizeof(Register)))); + + store32(TrustedImm32(Int32Tag), intTagFor(registerOffset + RegisterFile::ArgumentCount)); + store32(Imm32(argCount), intPayloadFor(registerOffset + RegisterFile::ArgumentCount)); storePtr(callFrameRegister, Address(callFrameRegister, (registerOffset + RegisterFile::CallerFrame) * static_cast<int>(sizeof(Register)))); storePtr(regT0, Address(callFrameRegister, (registerOffset + RegisterFile::Callee) * static_cast<int>(sizeof(Register)))); storePtr(regT1, Address(callFrameRegister, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register)))); @@ -224,7 +227,7 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>: // Fast check for JS function. Jump callLinkFailNotObject = emitJumpIfNotJSCell(regT0); - Jump callLinkFailNotJSFunction = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr)); + Jump callLinkFailNotJSFunction = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr)); // Speculatively roll the callframe, assuming argCount will match the arity. storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)))); diff --git a/Source/JavaScriptCore/jit/JITCall32_64.cpp b/Source/JavaScriptCore/jit/JITCall32_64.cpp index ac231a9..9ffa495 100644 --- a/Source/JavaScriptCore/jit/JITCall32_64.cpp +++ b/Source/JavaScriptCore/jit/JITCall32_64.cpp @@ -49,10 +49,10 @@ namespace JSC { void JIT::compileOpCallInitializeCallFrame() { // regT0 holds callee, regT1 holds argCount - store32(regT1, Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)))); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT3); // scopeChain - storePtr(regT0, Address(callFrameRegister, RegisterFile::Callee * static_cast<int>(sizeof(Register)))); // callee - storePtr(regT3, Address(callFrameRegister, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register)))); // scopeChain + emitPutIntToCallFrameHeader(regT1, RegisterFile::ArgumentCount); + emitPutCellToCallFrameHeader(regT0, RegisterFile::Callee); + emitPutCellToCallFrameHeader(regT3, RegisterFile::ScopeChain); } void JIT::emit_op_call_put_result(Instruction* instruction) @@ -72,12 +72,13 @@ void JIT::compileOpCallVarargs(Instruction* instruction) addPtr(Imm32(registerOffset), regT2, regT3); // registerOffset emitJumpSlowCaseIfNotJSCell(callee, regT1); - addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr))); + addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr))); // Speculatively roll the callframe, assuming argCount will match the arity. - mul32(Imm32(sizeof(Register)), regT3, regT3); + mul32(TrustedImm32(sizeof(Register)), regT3, regT3); addPtr(callFrameRegister, regT3); - storePtr(callFrameRegister, Address(regT3, RegisterFile::CallerFrame * static_cast<int>(sizeof(Register)))); + store32(TrustedImm32(JSValue::CellTag), tagFor(RegisterFile::CallerFrame, regT3)); + storePtr(callFrameRegister, payloadFor(RegisterFile::CallerFrame, regT3)); move(regT3, callFrameRegister); move(regT2, regT1); // argCount @@ -121,9 +122,9 @@ void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction) unsigned thisReg = currentInstruction[2].u.operand; emitLoad(result, regT1, regT0); - Jump notJSCell = branch32(NotEqual, regT1, Imm32(JSValue::CellTag)); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - Jump notObject = branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType)); + Jump notJSCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); + Jump notObject = branch8(NotEqual, Address(regT2, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType)); emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2); emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); @@ -199,18 +200,19 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned) stubCall.addArgument(JIT::Imm32(registerOffset)); stubCall.addArgument(JIT::Imm32(argCount)); stubCall.call(); - wasEval = branch32(NotEqual, regT1, Imm32(JSValue::EmptyValueTag)); + wasEval = branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag)); } emitLoad(callee, regT1, regT0); emitJumpSlowCaseIfNotJSCell(callee, regT1); - addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr))); + addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr))); // Speculatively roll the callframe, assuming argCount will match the arity. - storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)))); + store32(TrustedImm32(JSValue::CellTag), tagFor(RegisterFile::CallerFrame + registerOffset, callFrameRegister)); + storePtr(callFrameRegister, payloadFor(RegisterFile::CallerFrame + registerOffset, callFrameRegister)); addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister); - move(Imm32(argCount), regT1); + move(TrustedImm32(argCount), regT1); emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstruct() : m_globalData->jitStubs->ctiVirtualCall()); @@ -255,7 +257,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca stubCall.addArgument(JIT::Imm32(registerOffset)); stubCall.addArgument(JIT::Imm32(argCount)); stubCall.call(); - wasEval = branch32(NotEqual, regT1, Imm32(JSValue::EmptyValueTag)); + wasEval = branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag)); } emitLoad(callee, regT1, regT0); @@ -264,7 +266,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall); - Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, ImmPtr(0)); + Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(0)); END_UNINTERRUPTED_SEQUENCE(sequenceOpCall); @@ -272,7 +274,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca ASSERT_JIT_OFFSET(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow), patchOffsetOpCallCompareToJump); m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck; - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag))); // The following is the fast case, only used whan a callee can be linked. @@ -280,10 +282,12 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca // Note that this omits to set up RegisterFile::CodeBlock, which is set in the callee loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT2); - store32(Imm32(argCount), Address(callFrameRegister, (registerOffset + RegisterFile::ArgumentCount) * static_cast<int>(sizeof(Register)))); - storePtr(callFrameRegister, Address(callFrameRegister, (registerOffset + RegisterFile::CallerFrame) * static_cast<int>(sizeof(Register)))); + store32(TrustedImm32(JSValue::Int32Tag), tagFor(registerOffset + RegisterFile::ArgumentCount)); + store32(Imm32(argCount), payloadFor(registerOffset + RegisterFile::ArgumentCount)); + storePtr(callFrameRegister, payloadFor(RegisterFile::CallerFrame + registerOffset, callFrameRegister)); emitStore(registerOffset + RegisterFile::Callee, regT1, regT0); - storePtr(regT2, Address(callFrameRegister, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register)))); + store32(TrustedImm32(JSValue::CellTag), tagFor(registerOffset + RegisterFile::ScopeChain)); + store32(regT2, payloadFor(registerOffset + RegisterFile::ScopeChain)); addPtr(Imm32(registerOffset * sizeof(Register)), callFrameRegister); // Call to the callee @@ -305,11 +309,12 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>: linkSlowCase(iter); // Fast check for JS function. - Jump callLinkFailNotObject = branch32(NotEqual, regT1, Imm32(JSValue::CellTag)); - Jump callLinkFailNotJSFunction = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr)); + Jump callLinkFailNotObject = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); + Jump callLinkFailNotJSFunction = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr)); // Speculatively roll the callframe, assuming argCount will match the arity. - storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)))); + store32(TrustedImm32(JSValue::CellTag), tagFor(RegisterFile::CallerFrame + registerOffset, callFrameRegister)); + storePtr(callFrameRegister, payloadFor(RegisterFile::CallerFrame + registerOffset, callFrameRegister)); addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister); move(Imm32(argCount), regT1); diff --git a/Source/JavaScriptCore/jit/JITInlineMethods.h b/Source/JavaScriptCore/jit/JITInlineMethods.h index 39ca4a5..16c2335 100644 --- a/Source/JavaScriptCore/jit/JITInlineMethods.h +++ b/Source/JavaScriptCore/jit/JITInlineMethods.h @@ -52,12 +52,26 @@ ALWAYS_INLINE JSValue JIT::getConstantOperand(unsigned src) ALWAYS_INLINE void JIT::emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry) { - storePtr(from, Address(callFrameRegister, entry * sizeof(Register))); + storePtr(from, payloadFor(entry, callFrameRegister)); +} + +ALWAYS_INLINE void JIT::emitPutCellToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry) +{ +#if USE(JSVALUE32_64) + store32(TrustedImm32(JSValue::CellTag), tagFor(entry, callFrameRegister)); +#endif + storePtr(from, payloadFor(entry, callFrameRegister)); +} + +ALWAYS_INLINE void JIT::emitPutIntToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry) +{ + store32(TrustedImm32(Int32Tag), intTagFor(entry, callFrameRegister)); + store32(from, intPayloadFor(entry, callFrameRegister)); } ALWAYS_INLINE void JIT::emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry) { - storePtr(ImmPtr(value), Address(callFrameRegister, entry * sizeof(Register))); + storePtr(TrustedImmPtr(value), Address(callFrameRegister, entry * sizeof(Register))); } ALWAYS_INLINE void JIT::emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from) @@ -70,9 +84,9 @@ ALWAYS_INLINE void JIT::emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHea ALWAYS_INLINE void JIT::emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures) { - failures.append(branchPtr(NotEqual, Address(src), ImmPtr(m_globalData->jsStringVPtr))); + failures.append(branchPtr(NotEqual, Address(src), TrustedImmPtr(m_globalData->jsStringVPtr))); failures.append(branchTest32(NonZero, Address(src, OBJECT_OFFSETOF(JSString, m_fiberCount)))); - failures.append(branch32(NotEqual, MacroAssembler::Address(src, ThunkHelpers::jsStringLengthOffset()), Imm32(1))); + failures.append(branch32(NotEqual, MacroAssembler::Address(src, ThunkHelpers::jsStringLengthOffset()), TrustedImm32(1))); loadPtr(MacroAssembler::Address(src, ThunkHelpers::jsStringValueOffset()), dst); loadPtr(MacroAssembler::Address(dst, ThunkHelpers::stringImplDataOffset()), dst); load16(MacroAssembler::Address(dst, 0), dst); @@ -200,7 +214,7 @@ ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() { #if CPU(X86) // Within a trampoline the return address will be on the stack at this point. - addPtr(Imm32(sizeof(void*)), stackPointerRegister, firstArgumentRegister); + addPtr(TrustedImm32(sizeof(void*)), stackPointerRegister, firstArgumentRegister); #elif CPU(ARM) move(stackPointerRegister, firstArgumentRegister); #endif @@ -209,7 +223,7 @@ ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() ALWAYS_INLINE JIT::Jump JIT::checkStructure(RegisterID reg, Structure* structure) { - return branchPtr(NotEqual, Address(reg, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(structure)); + return branchPtr(NotEqual, Address(reg, JSCell::structureOffset()), TrustedImmPtr(structure)); } ALWAYS_INLINE void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator& iter, int vReg) @@ -254,14 +268,14 @@ ALWAYS_INLINE void JIT::setSamplingFlag(int32_t flag) { ASSERT(flag >= 1); ASSERT(flag <= 32); - or32(Imm32(1u << (flag - 1)), AbsoluteAddress(&SamplingFlags::s_flags)); + or32(TrustedImm32(1u << (flag - 1)), AbsoluteAddress(&SamplingFlags::s_flags)); } ALWAYS_INLINE void JIT::clearSamplingFlag(int32_t flag) { ASSERT(flag >= 1); ASSERT(flag <= 32); - and32(Imm32(~(1u << (flag - 1))), AbsoluteAddress(&SamplingFlags::s_flags)); + and32(TrustedImm32(~(1u << (flag - 1))), AbsoluteAddress(&SamplingFlags::s_flags)); } #endif @@ -269,11 +283,11 @@ ALWAYS_INLINE void JIT::clearSamplingFlag(int32_t flag) ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, uint32_t count) { #if CPU(X86_64) // Or any other 64-bit plattform. - addPtr(Imm32(count), AbsoluteAddress(&counter.m_counter)); + addPtr(TrustedImm32(count), AbsoluteAddress(counter.addressOfCounter())); #elif CPU(X86) // Or any other little-endian 32-bit plattform. - intptr_t hiWord = reinterpret_cast<intptr_t>(&counter.m_counter) + sizeof(int32_t); - add32(Imm32(count), AbsoluteAddress(&counter.m_counter)); - addWithCarry32(Imm32(0), AbsoluteAddress(reinterpret_cast<void*>(hiWord))); + intptr_t hiWord = reinterpret_cast<intptr_t>(counter.addressOfCounter()) + sizeof(int32_t); + add32(TrustedImm32(count), AbsoluteAddress(counter.addressOfCounter())); + addWithCarry32(TrustedImm32(0), AbsoluteAddress(reinterpret_cast<void*>(hiWord))); #else #error "SAMPLING_FLAGS not implemented on this platform." #endif @@ -284,13 +298,13 @@ ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, uint32_t cou #if CPU(X86_64) ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction) { - move(ImmPtr(m_interpreter->sampler()->sampleSlot()), X86Registers::ecx); - storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), X86Registers::ecx); + move(TrustedImmPtr(m_interpreter->sampler()->sampleSlot()), X86Registers::ecx); + storePtr(TrustedImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), X86Registers::ecx); } #else ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction) { - storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), m_interpreter->sampler()->sampleSlot()); + storePtr(TrustedImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), m_interpreter->sampler()->sampleSlot()); } #endif #endif @@ -299,13 +313,13 @@ ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostF #if CPU(X86_64) ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock) { - move(ImmPtr(m_interpreter->sampler()->codeBlockSlot()), X86Registers::ecx); - storePtr(ImmPtr(codeBlock), X86Registers::ecx); + move(TrustedImmPtr(m_interpreter->sampler()->codeBlockSlot()), X86Registers::ecx); + storePtr(TrustedImmPtr(codeBlock), X86Registers::ecx); } #else ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock) { - storePtr(ImmPtr(codeBlock), m_interpreter->sampler()->codeBlockSlot()); + storePtr(TrustedImmPtr(codeBlock), m_interpreter->sampler()->codeBlockSlot()); } #endif #endif @@ -396,7 +410,7 @@ inline void JIT::emitLoad2(unsigned index1, RegisterID tag1, RegisterID payload1 inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value) { if (m_codeBlock->isConstantRegisterIndex(index)) { - Register& inConstantPool = m_codeBlock->constantRegister(index); + WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index); loadDouble(&inConstantPool, value); } else loadDouble(addressFor(index), value); @@ -405,7 +419,7 @@ inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value) inline void JIT::emitLoadInt32ToDouble(unsigned index, FPRegisterID value) { if (m_codeBlock->isConstantRegisterIndex(index)) { - Register& inConstantPool = m_codeBlock->constantRegister(index); + WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index); char* bytePointer = reinterpret_cast<char*>(&inConstantPool); convertInt32ToDouble(AbsoluteAddress(bytePointer + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), value); } else @@ -422,27 +436,27 @@ inline void JIT::emitStoreInt32(unsigned index, RegisterID payload, bool indexIs { store32(payload, payloadFor(index, callFrameRegister)); if (!indexIsInt32) - store32(Imm32(JSValue::Int32Tag), tagFor(index, callFrameRegister)); + store32(TrustedImm32(JSValue::Int32Tag), tagFor(index, callFrameRegister)); } -inline void JIT::emitStoreInt32(unsigned index, Imm32 payload, bool indexIsInt32) +inline void JIT::emitStoreInt32(unsigned index, TrustedImm32 payload, bool indexIsInt32) { store32(payload, payloadFor(index, callFrameRegister)); if (!indexIsInt32) - store32(Imm32(JSValue::Int32Tag), tagFor(index, callFrameRegister)); + store32(TrustedImm32(JSValue::Int32Tag), tagFor(index, callFrameRegister)); } inline void JIT::emitStoreCell(unsigned index, RegisterID payload, bool indexIsCell) { store32(payload, payloadFor(index, callFrameRegister)); if (!indexIsCell) - store32(Imm32(JSValue::CellTag), tagFor(index, callFrameRegister)); + store32(TrustedImm32(JSValue::CellTag), tagFor(index, callFrameRegister)); } inline void JIT::emitStoreBool(unsigned index, RegisterID tag, bool indexIsBool) { if (!indexIsBool) - store32(Imm32(0), payloadFor(index, callFrameRegister)); + store32(TrustedImm32(0), payloadFor(index, callFrameRegister)); store32(tag, tagFor(index, callFrameRegister)); } @@ -550,7 +564,7 @@ inline void JIT::emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex, Regi if (m_codeBlock->isConstantRegisterIndex(virtualRegisterIndex)) addSlowCase(jump()); else - addSlowCase(branch32(NotEqual, tag, Imm32(JSValue::CellTag))); + addSlowCase(branch32(NotEqual, tag, TrustedImm32(JSValue::CellTag))); } } @@ -652,7 +666,7 @@ ALWAYS_INLINE void JIT::emitPutVirtualRegister(unsigned dst, RegisterID from) ALWAYS_INLINE void JIT::emitInitRegister(unsigned dst) { - storePtr(ImmPtr(JSValue::encode(jsUndefined())), Address(callFrameRegister, dst * sizeof(Register))); + storePtr(TrustedImmPtr(JSValue::encode(jsUndefined())), Address(callFrameRegister, dst * sizeof(Register))); } ALWAYS_INLINE JIT::Jump JIT::emitJumpIfJSCell(RegisterID reg) @@ -660,7 +674,7 @@ ALWAYS_INLINE JIT::Jump JIT::emitJumpIfJSCell(RegisterID reg) #if USE(JSVALUE64) return branchTestPtr(Zero, reg, tagMaskRegister); #else - return branchTest32(Zero, reg, Imm32(JSImmediate::TagMask)); + return branchTest32(Zero, reg, TrustedImm32(JSImmediate::TagMask)); #endif } @@ -681,7 +695,7 @@ ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotJSCell(RegisterID reg) #if USE(JSVALUE64) return branchTestPtr(NonZero, reg, tagMaskRegister); #else - return branchTest32(NonZero, reg, Imm32(JSImmediate::TagMask)); + return branchTest32(NonZero, reg, TrustedImm32(JSImmediate::TagMask)); #endif } @@ -701,7 +715,7 @@ ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg, int vReg) inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value) { if (m_codeBlock->isConstantRegisterIndex(index)) { - Register& inConstantPool = m_codeBlock->constantRegister(index); + WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index); loadDouble(&inConstantPool, value); } else loadDouble(addressFor(index), value); @@ -710,8 +724,8 @@ inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value) inline void JIT::emitLoadInt32ToDouble(unsigned index, FPRegisterID value) { if (m_codeBlock->isConstantRegisterIndex(index)) { - Register& inConstantPool = m_codeBlock->constantRegister(index); - convertInt32ToDouble(AbsoluteAddress(&inConstantPool), value); + ASSERT(isOperandConstantImmediateInt(index)); + convertInt32ToDouble(Imm32(getConstantOperand(index).asInt32()), value); } else convertInt32ToDouble(addressFor(index), value); } @@ -722,7 +736,7 @@ ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateInteger(RegisterID reg) #if USE(JSVALUE64) return branchPtr(AboveOrEqual, reg, tagTypeNumberRegister); #else - return branchTest32(NonZero, reg, Imm32(JSImmediate::TagTypeNumber)); + return branchTest32(NonZero, reg, TrustedImm32(JSImmediate::TagTypeNumber)); #endif } @@ -731,7 +745,7 @@ ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateInteger(RegisterID reg) #if USE(JSVALUE64) return branchPtr(Below, reg, tagTypeNumberRegister); #else - return branchTest32(Zero, reg, Imm32(JSImmediate::TagTypeNumber)); + return branchTest32(Zero, reg, TrustedImm32(JSImmediate::TagTypeNumber)); #endif } @@ -760,12 +774,12 @@ ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateNumber(RegisterID reg) #if USE(JSVALUE32_64) ALWAYS_INLINE void JIT::emitFastArithDeTagImmediate(RegisterID reg) { - subPtr(Imm32(JSImmediate::TagTypeNumber), reg); + subPtr(TrustedImm32(JSImmediate::TagTypeNumber), reg); } ALWAYS_INLINE JIT::Jump JIT::emitFastArithDeTagImmediateJumpIfZero(RegisterID reg) { - return branchSubPtr(Zero, Imm32(JSImmediate::TagTypeNumber), reg); + return branchSubPtr(Zero, TrustedImm32(JSImmediate::TagTypeNumber), reg); } #endif @@ -776,7 +790,7 @@ ALWAYS_INLINE void JIT::emitFastArithReTagImmediate(RegisterID src, RegisterID d #else if (src != dest) move(src, dest); - addPtr(Imm32(JSImmediate::TagTypeNumber), dest); + addPtr(TrustedImm32(JSImmediate::TagTypeNumber), dest); #endif } @@ -796,8 +810,8 @@ ALWAYS_INLINE void JIT::emitFastArithIntToImmNoCheck(RegisterID src, RegisterID ALWAYS_INLINE void JIT::emitTagAsBoolImmediate(RegisterID reg) { - lshift32(Imm32(JSImmediate::ExtendedPayloadShift), reg); - or32(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), reg); + lshift32(TrustedImm32(JSImmediate::ExtendedPayloadShift), reg); + or32(TrustedImm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), reg); } #endif // USE(JSVALUE32_64) diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp index fc769db..daceea6 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp @@ -52,12 +52,12 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable // Check eax is a string Jump string_failureCases1 = emitJumpIfNotJSCell(regT0); - Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)); + Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)); // Checks out okay! - get the length from the Ustring. load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_length)), regT0); - Jump string_failureCases3 = branch32(Above, regT0, Imm32(JSImmediate::maxImmediateInt)); + Jump string_failureCases3 = branch32(Above, regT0, TrustedImm32(JSImmediate::maxImmediateInt)); // regT0 contains a 64 bit value (is positive, is zero extended) so we don't need sign extend here. emitFastArithIntToImmNoCheck(regT0, regT0); @@ -102,7 +102,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); - Jump hasCodeBlock3 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForCall)), Imm32(0)); + Jump hasCodeBlock3 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForCall)), TrustedImm32(0)); preserveReturnAddressAfterCall(regT3); restoreArgumentReference(); Call callCompileCall = call(); @@ -122,7 +122,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); - Jump hasCodeBlock4 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForConstruct)), Imm32(0)); + Jump hasCodeBlock4 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForConstruct)), TrustedImm32(0)); preserveReturnAddressAfterCall(regT3); restoreArgumentReference(); Call callCompileConstruct = call(); @@ -141,10 +141,10 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1); emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); restoreReturnAddressBeforeReturn(regT1); - move(ImmPtr(&globalData->exceptionLocation), regT2); + move(TrustedImmPtr(&globalData->exceptionLocation), regT2); storePtr(regT1, regT2); poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); - poke(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value())); + poke(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value())); ret(); // NativeCall Trampoline @@ -199,7 +199,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon // get to its global data. emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0); emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0); - emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); peek(regT1); emitPutToCallFrameHeader(regT1, RegisterFile::ReturnPC); @@ -208,21 +208,21 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon // Host function signature: f(ExecState*); move(callFrameRegister, X86Registers::edi); - subPtr(Imm32(16 - sizeof(void*)), stackPointerRegister); // Align stack after call. + subPtr(TrustedImm32(16 - sizeof(void*)), stackPointerRegister); // Align stack after call. emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::esi); loadPtr(Address(X86Registers::esi, OBJECT_OFFSETOF(JSFunction, m_executable)), X86Registers::r9); move(regT0, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack. call(Address(X86Registers::r9, executableOffsetToFunction)); - addPtr(Imm32(16 - sizeof(void*)), stackPointerRegister); + addPtr(TrustedImm32(16 - sizeof(void*)), stackPointerRegister); #elif CPU(ARM) // Load caller frame's scope chain into this callframe so that whatever we call can // get to its global data. emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2); emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2); - emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); preserveReturnAddressAfterCall(regT3); // Callee preserved emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); @@ -243,7 +243,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon // get to its global data. emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0); emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0); - emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); preserveReturnAddressAfterCall(regT3); // Callee preserved emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); @@ -253,7 +253,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon // Allocate stack space for 16 bytes (8-byte aligned) // 16 bytes (unused) for 4 arguments - subPtr(Imm32(16), stackPointerRegister); + subPtr(TrustedImm32(16), stackPointerRegister); // Setup arg0 move(callFrameRegister, MIPSRegisters::a0); @@ -265,7 +265,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon call(Address(regT2, executableOffsetToFunction)); // Restore stack space - addPtr(Imm32(16), stackPointerRegister); + addPtr(TrustedImm32(16), stackPointerRegister); restoreReturnAddressBeforeReturn(regT3); @@ -289,12 +289,12 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon // Grab the return address. preserveReturnAddressAfterCall(regT1); - move(ImmPtr(&globalData->exceptionLocation), regT2); + move(TrustedImmPtr(&globalData->exceptionLocation), regT2); storePtr(regT1, regT2); poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); // Set the return address. - move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1); + move(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1); restoreReturnAddressBeforeReturn(regT1); ret(); @@ -378,8 +378,8 @@ void JIT::emit_op_check_has_instance(Instruction* currentInstruction) emitJumpSlowCaseIfNotJSCell(regT0, baseVal); // Check that baseVal 'ImplementsHasInstance'. - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0); - addSlowCase(branchTest8(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsHasInstance))); + loadPtr(Address(regT0, JSCell::structureOffset()), regT0); + addSlowCase(branchTest8(Zero, Address(regT0, Structure::typeInfoFlagsOffset()), TrustedImm32(ImplementsHasInstance))); } void JIT::emit_op_instanceof(Instruction* currentInstruction) @@ -400,29 +400,29 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction) emitJumpSlowCaseIfNotJSCell(regT1, proto); // Check that prototype is an object - loadPtr(Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), regT3); - addSlowCase(branch8(NotEqual, Address(regT3, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); + loadPtr(Address(regT1, JSCell::structureOffset()), regT3); + addSlowCase(branch8(NotEqual, Address(regT3, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType))); // Fixme: this check is only needed because the JSC API allows HasInstance to be overridden; we should deprecate this. // Check that baseVal 'ImplementsDefaultHasInstance'. - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0); - addSlowCase(branchTest8(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance))); + loadPtr(Address(regT0, JSCell::structureOffset()), regT0); + addSlowCase(branchTest8(Zero, Address(regT0, Structure::typeInfoFlagsOffset()), TrustedImm32(ImplementsDefaultHasInstance))); // Optimistically load the result true, and start looping. // Initially, regT1 still contains proto and regT2 still contains value. // As we loop regT2 will be updated with its prototype, recursively walking the prototype chain. - move(ImmPtr(JSValue::encode(jsBoolean(true))), regT0); + move(TrustedImmPtr(JSValue::encode(jsBoolean(true))), regT0); Label loop(this); // Load the prototype of the object in regT2. If this is equal to regT1 - WIN! // Otherwise, check if we've hit null - if we have then drop out of the loop, if not go again. - loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2); + loadPtr(Address(regT2, JSCell::structureOffset()), regT2); + loadPtr(Address(regT2, Structure::prototypeOffset()), regT2); Jump isInstance = branchPtr(Equal, regT2, regT1); emitJumpIfJSCell(regT2).linkTo(loop, this); // We get here either by dropping out of the loop, or if value was not an Object. Result is false. - move(ImmPtr(JSValue::encode(jsBoolean(false))), regT0); + move(TrustedImmPtr(JSValue::encode(jsBoolean(false))), regT0); // isInstance jumps right down to here, to skip setting the result to false (it has already set true). isInstance.link(this); @@ -452,7 +452,7 @@ void JIT::emit_op_construct(Instruction* currentInstruction) void JIT::emit_op_get_global_var(Instruction* currentInstruction) { JSVariableObject* globalObject = m_codeBlock->globalObject(); - loadPtr(&globalObject->d->registers, regT0); + loadPtr(&globalObject->m_registers, regT0); loadPtr(Address(regT0, currentInstruction[2].u.operand * sizeof(Register)), regT0); emitPutVirtualRegister(currentInstruction[1].u.operand); } @@ -461,7 +461,7 @@ void JIT::emit_op_put_global_var(Instruction* currentInstruction) { emitGetVirtualRegister(currentInstruction[2].u.operand, regT1); JSVariableObject* globalObject = m_codeBlock->globalObject(); - loadPtr(&globalObject->d->registers, regT0); + loadPtr(&globalObject->m_registers, regT0); storePtr(regT1, Address(regT0, currentInstruction[1].u.operand * sizeof(Register))); } @@ -483,8 +483,7 @@ void JIT::emit_op_get_scoped_var(Instruction* currentInstruction) loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0); loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT0); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSVariableObject, d)), regT0); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), regT0); + loadPtr(Address(regT0, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT0); loadPtr(Address(regT0, currentInstruction[2].u.operand * sizeof(Register)), regT0); emitPutVirtualRegister(currentInstruction[1].u.operand); } @@ -508,8 +507,7 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction) loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1); loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1); - loadPtr(Address(regT1, OBJECT_OFFSETOF(JSVariableObject, d)), regT1); - loadPtr(Address(regT1, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), regT1); + loadPtr(Address(regT1, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT1); storePtr(regT0, Address(regT1, currentInstruction[1].u.operand * sizeof(Register))); } @@ -567,8 +565,8 @@ void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction) // Return the result in %eax. emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister); Jump notJSCell = emitJumpIfNotJSCell(returnValueRegister); - loadPtr(Address(returnValueRegister, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - Jump notObject = branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType)); + loadPtr(Address(returnValueRegister, JSCell::structureOffset()), regT2); + Jump notObject = branch8(NotEqual, Address(regT2, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType)); // Grab the return address. emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1); @@ -607,7 +605,7 @@ void JIT::emit_op_new_array(Instruction* currentInstruction) void JIT::emit_op_resolve(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.call(currentInstruction[1].u.operand); } @@ -619,7 +617,7 @@ void JIT::emit_op_to_primitive(Instruction* currentInstruction) emitGetVirtualRegister(src, regT0); Jump isImm = emitJumpIfNotJSCell(regT0); - addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr))); + addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr))); isImm.link(this); if (dst != src) @@ -638,7 +636,7 @@ void JIT::emit_op_strcat(Instruction* currentInstruction) void JIT::emit_op_resolve_base(Instruction* currentInstruction) { JITStubCall stubCall(this, currentInstruction[3].u.operand ? cti_op_resolve_base_strict_put : cti_op_resolve_base); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.call(currentInstruction[1].u.operand); } @@ -646,14 +644,14 @@ void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_ensure_property_exists); stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.call(currentInstruction[1].u.operand); } void JIT::emit_op_resolve_skip(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve_skip); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); stubCall.call(currentInstruction[1].u.operand); } @@ -667,9 +665,9 @@ void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool) void* offsetAddr = &(m_codeBlock->globalResolveInfo(currentIndex).offset); // Check Structure of global object - move(ImmPtr(globalObject), regT0); + move(TrustedImmPtr(globalObject), regT0); loadPtr(structureAddress, regT1); - addSlowCase(branchPtr(NotEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)))); // Structures don't match + addSlowCase(branchPtr(NotEqual, regT1, Address(regT0, JSCell::structureOffset()))); // Structures don't match // Load cached property // Assume that the global object always uses external storage. @@ -688,7 +686,7 @@ void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<Slo linkSlowCase(iter); JITStubCall stubCall(this, cti_op_resolve_global); - stubCall.addArgument(ImmPtr(ident)); + stubCall.addArgument(TrustedImmPtr(ident)); stubCall.addArgument(Imm32(currentIndex)); stubCall.addArgument(regT0); stubCall.call(dst); @@ -697,9 +695,9 @@ void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<Slo void JIT::emit_op_not(Instruction* currentInstruction) { emitGetVirtualRegister(currentInstruction[2].u.operand, regT0); - xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), regT0); - addSlowCase(branchTestPtr(NonZero, regT0, Imm32(static_cast<int32_t>(~JSImmediate::ExtendedPayloadBitBoolValue)))); - xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue)), regT0); + xorPtr(TrustedImm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), regT0); + addSlowCase(branchTestPtr(NonZero, regT0, TrustedImm32(static_cast<int32_t>(~JSImmediate::ExtendedPayloadBitBoolValue)))); + xorPtr(TrustedImm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue)), regT0); emitPutVirtualRegister(currentInstruction[1].u.operand); } @@ -708,11 +706,11 @@ void JIT::emit_op_jfalse(Instruction* currentInstruction) unsigned target = currentInstruction[2].u.operand; emitGetVirtualRegister(currentInstruction[1].u.operand, regT0); - addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(0)))), target); + addJump(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(jsNumber(0)))), target); Jump isNonZero = emitJumpIfImmediateInteger(regT0); - addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))), target); - addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(true))))); + addJump(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(jsBoolean(false)))), target); + addSlowCase(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(jsBoolean(true))))); isNonZero.link(this); RECORD_JUMP_TARGET(target); @@ -727,14 +725,14 @@ void JIT::emit_op_jeq_null(Instruction* currentInstruction) Jump isImmediate = emitJumpIfNotJSCell(regT0); // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - addJump(branchTest8(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); + addJump(branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)), target); Jump wasNotImmediate = jump(); // Now handle the immediate cases - undefined & null isImmediate.link(this); - andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0); - addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNull()))), target); + andPtr(TrustedImm32(~JSImmediate::ExtendedTagBitUndefined), regT0); + addJump(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(jsNull()))), target); wasNotImmediate.link(this); RECORD_JUMP_TARGET(target); @@ -748,14 +746,14 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction) Jump isImmediate = emitJumpIfNotJSCell(regT0); // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - addJump(branchTest8(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); + addJump(branchTest8(Zero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)), target); Jump wasNotImmediate = jump(); // Now handle the immediate cases - undefined & null isImmediate.link(this); - andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0); - addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsNull()))), target); + andPtr(TrustedImm32(~JSImmediate::ExtendedTagBitUndefined), regT0); + addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(jsNull()))), target); wasNotImmediate.link(this); RECORD_JUMP_TARGET(target); @@ -764,11 +762,11 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction) void JIT::emit_op_jneq_ptr(Instruction* currentInstruction) { unsigned src = currentInstruction[1].u.operand; - JSCell* ptr = currentInstruction[2].u.jsCell; + JSCell* ptr = currentInstruction[2].u.jsCell.get(); unsigned target = currentInstruction[3].u.operand; emitGetVirtualRegister(src, regT0); - addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue(ptr)))), target); + addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue(ptr)))), target); RECORD_JUMP_TARGET(target); } @@ -777,7 +775,7 @@ void JIT::emit_op_jsr(Instruction* currentInstruction) { int retAddrDst = currentInstruction[1].u.operand; int target = currentInstruction[2].u.operand; - DataLabelPtr storeLocation = storePtrWithPatch(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst)); + DataLabelPtr storeLocation = storePtrWithPatch(TrustedImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst)); addJump(jump(), target); m_jsrSites.append(JSRInfo(storeLocation, label())); killLastResultRegister(); @@ -811,7 +809,7 @@ void JIT::emit_op_bitnot(Instruction* currentInstruction) void JIT::emit_op_resolve_with_base(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve_with_base); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand))); stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); stubCall.call(currentInstruction[2].u.operand); } @@ -819,7 +817,7 @@ void JIT::emit_op_resolve_with_base(Instruction* currentInstruction) void JIT::emit_op_new_func_exp(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_new_func_exp); - stubCall.addArgument(ImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand))); stubCall.call(currentInstruction[1].u.operand); } @@ -828,11 +826,11 @@ void JIT::emit_op_jtrue(Instruction* currentInstruction) unsigned target = currentInstruction[2].u.operand; emitGetVirtualRegister(currentInstruction[1].u.operand, regT0); - Jump isZero = branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(0)))); + Jump isZero = branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(jsNumber(0)))); addJump(emitJumpIfImmediateInteger(regT0), target); - addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))), target); - addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(false))))); + addJump(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(jsBoolean(true)))), target); + addSlowCase(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(jsBoolean(false))))); isZero.link(this); RECORD_JUMP_TARGET(target); @@ -893,8 +891,8 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction) if (!m_codeBlock->isKnownNotImmediate(base)) isNotObject.append(emitJumpIfNotJSCell(regT0)); if (base != m_codeBlock->thisRegister() || m_codeBlock->isStrictMode()) { - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - isNotObject.append(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); + isNotObject.append(branch8(NotEqual, Address(regT2, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType))); } // We could inline the case where you have a valid cache, but @@ -904,14 +902,15 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction) getPnamesStubCall.addArgument(regT0); getPnamesStubCall.call(dst); load32(Address(regT0, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStringsSize)), regT3); - store32(Imm32(0), addressFor(i)); - store32(regT3, addressFor(size)); + storePtr(tagTypeNumberRegister, payloadFor(i)); + store32(TrustedImm32(Int32Tag), intTagFor(size)); + store32(regT3, intPayloadFor(size)); Jump end = jump(); isNotObject.link(this); move(regT0, regT1); - and32(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT1); - addJump(branch32(Equal, regT1, Imm32(JSImmediate::FullTagTypeNull)), breakTarget); + and32(TrustedImm32(~JSImmediate::ExtendedTagBitUndefined), regT1); + addJump(branch32(Equal, regT1, TrustedImm32(JSImmediate::FullTagTypeNull)), breakTarget); JITStubCall toObjectStubCall(this, cti_to_object); toObjectStubCall.addArgument(regT0); @@ -933,8 +932,8 @@ void JIT::emit_op_next_pname(Instruction* currentInstruction) JumpList callHasProperty; Label begin(this); - load32(addressFor(i), regT0); - Jump end = branch32(Equal, regT0, addressFor(size)); + load32(intPayloadFor(i), regT0); + Jump end = branch32(Equal, regT0, intPayloadFor(size)); // Grab key @ i loadPtr(addressFor(it), regT1); @@ -945,14 +944,14 @@ void JIT::emit_op_next_pname(Instruction* currentInstruction) emitPutVirtualRegister(dst, regT2); // Increment i - add32(Imm32(1), regT0); - store32(regT0, addressFor(i)); + add32(TrustedImm32(1), regT0); + store32(regT0, intPayloadFor(i)); // Verify that i is valid: emitGetVirtualRegister(base, regT0); // Test base's structure - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); callHasProperty.append(branchPtr(NotEqual, regT2, Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure))))); // Test base's prototype chain @@ -961,11 +960,11 @@ void JIT::emit_op_next_pname(Instruction* currentInstruction) addJump(branchTestPtr(Zero, Address(regT3)), target); Label checkPrototype(this); - loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2); + loadPtr(Address(regT2, Structure::prototypeOffset()), regT2); callHasProperty.append(emitJumpIfNotJSCell(regT2)); - loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); + loadPtr(Address(regT2, JSCell::structureOffset()), regT2); callHasProperty.append(branchPtr(NotEqual, regT2, Address(regT3))); - addPtr(Imm32(sizeof(Structure*)), regT3); + addPtr(TrustedImm32(sizeof(Structure*)), regT3); branchTestPtr(NonZero, Address(regT3)).linkTo(checkPrototype, this); // Continue loop. @@ -1040,8 +1039,8 @@ void JIT::emit_op_to_jsnumber(Instruction* currentInstruction) Jump wasImmediate = emitJumpIfImmediateInteger(regT0); emitJumpSlowCaseIfNotJSCell(regT0, srcVReg); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - addSlowCase(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(NumberType))); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); + addSlowCase(branch8(NotEqual, Address(regT2, Structure::typeInfoTypeOffset()), TrustedImm32(NumberType))); wasImmediate.link(this); @@ -1051,7 +1050,7 @@ void JIT::emit_op_to_jsnumber(Instruction* currentInstruction) void JIT::emit_op_push_new_scope(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_push_new_scope); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.addArgument(currentInstruction[3].u.operand, regT2); stubCall.call(currentInstruction[1].u.operand); } @@ -1062,7 +1061,7 @@ void JIT::emit_op_catch(Instruction* currentInstruction) move(regT0, callFrameRegister); peek(regT3, OBJECT_OFFSETOF(struct JITStackFrame, globalData) / sizeof(void*)); loadPtr(Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception)), regT0); - storePtr(ImmPtr(JSValue::encode(JSValue())), Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception))); + storePtr(TrustedImmPtr(JSValue::encode(JSValue())), Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception))); emitPutVirtualRegister(currentInstruction[1].u.operand); } @@ -1157,15 +1156,15 @@ void JIT::emit_op_eq_null(Instruction* currentInstruction) emitGetVirtualRegister(src1, regT0); Jump isImmediate = emitJumpIfNotJSCell(regT0); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - set32Test8(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); + set32Test8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT0); Jump wasNotImmediate = jump(); isImmediate.link(this); - andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0); - setPtr(Equal, regT0, Imm32(JSImmediate::FullTagTypeNull), regT0); + andPtr(TrustedImm32(~JSImmediate::ExtendedTagBitUndefined), regT0); + setPtr(Equal, regT0, TrustedImm32(JSImmediate::FullTagTypeNull), regT0); wasNotImmediate.link(this); @@ -1182,15 +1181,15 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction) emitGetVirtualRegister(src1, regT0); Jump isImmediate = emitJumpIfNotJSCell(regT0); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - set32Test8(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); + set32Test8(Zero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT0); Jump wasNotImmediate = jump(); isImmediate.link(this); - andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0); - setPtr(NotEqual, regT0, Imm32(JSImmediate::FullTagTypeNull), regT0); + andPtr(TrustedImm32(~JSImmediate::ExtendedTagBitUndefined), regT0); + setPtr(NotEqual, regT0, TrustedImm32(JSImmediate::FullTagTypeNull), regT0); wasNotImmediate.link(this); @@ -1237,7 +1236,7 @@ void JIT::emit_op_init_lazy_reg(Instruction* currentInstruction) { unsigned dst = currentInstruction[1].u.operand; - storePtr(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * dst)); + storePtr(TrustedImmPtr(0), Address(callFrameRegister, sizeof(Register) * dst)); } void JIT::emit_op_convert_this(Instruction* currentInstruction) @@ -1245,22 +1244,22 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction) emitGetVirtualRegister(currentInstruction[1].u.operand, regT0); emitJumpSlowCaseIfNotJSCell(regT0); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1); - addSlowCase(branchTest8(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion))); + loadPtr(Address(regT0, JSCell::structureOffset()), regT1); + addSlowCase(branchTest8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(NeedsThisConversion))); } void JIT::emit_op_convert_this_strict(Instruction* currentInstruction) { emitGetVirtualRegister(currentInstruction[1].u.operand, regT0); Jump notNull = branchTestPtr(NonZero, regT0); - move(ImmPtr(JSValue::encode(jsNull())), regT0); + move(TrustedImmPtr(JSValue::encode(jsNull())), regT0); emitPutVirtualRegister(currentInstruction[1].u.operand, regT0); Jump setThis = jump(); notNull.link(this); Jump isImmediate = emitJumpIfNotJSCell(regT0); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1); - Jump notAnObject = branch8(NotEqual, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)); - addSlowCase(branchTest8(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion))); + loadPtr(Address(regT0, JSCell::structureOffset()), regT1); + Jump notAnObject = branch8(NotEqual, Address(regT1, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType)); + addSlowCase(branchTest8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(NeedsThisConversion))); isImmediate.link(this); notAnObject.link(this); setThis.link(this); @@ -1375,7 +1374,7 @@ void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCas void JIT::emitSlow_op_not(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) { linkSlowCase(iter); - xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), regT0); + xorPtr(TrustedImm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), regT0); JITStubCall stubCall(this, cti_op_not); stubCall.addArgument(regT0); stubCall.call(currentInstruction[1].u.operand); @@ -1443,7 +1442,7 @@ void JIT::emitSlow_op_neq(Instruction* currentInstruction, Vector<SlowCaseEntry> stubCall.addArgument(regT0); stubCall.addArgument(regT1); stubCall.call(); - xor32(Imm32(0x1), regT0); + xor32(TrustedImm32(0x1), regT0); emitTagAsBoolImmediate(regT0); emitPutVirtualRegister(currentInstruction[1].u.operand); } @@ -1533,7 +1532,7 @@ void JIT::emit_op_get_arguments_length(Instruction* currentInstruction) int argumentsRegister = currentInstruction[2].u.operand; addSlowCase(branchTestPtr(NonZero, addressFor(argumentsRegister))); emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0); - sub32(Imm32(1), regT0); + sub32(TrustedImm32(1), regT0); emitFastArithReTagImmediate(regT0, regT0); emitPutVirtualRegister(dst, regT0); } @@ -1548,7 +1547,7 @@ void JIT::emitSlow_op_get_arguments_length(Instruction* currentInstruction, Vect emitGetVirtualRegister(base, regT0); JITStubCall stubCall(this, cti_op_get_by_id_generic); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(ident)); + stubCall.addArgument(TrustedImmPtr(ident)); stubCall.call(dst); } @@ -1560,7 +1559,7 @@ void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction) addSlowCase(branchTestPtr(NonZero, addressFor(argumentsRegister))); emitGetVirtualRegister(property, regT1); addSlowCase(emitJumpIfNotImmediateInteger(regT1)); - add32(Imm32(1), regT1); + add32(TrustedImm32(1), regT1); // regT1 now contains the integer index of the argument we want, including this emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT2); addSlowCase(branch32(AboveOrEqual, regT1, regT2)); @@ -1576,7 +1575,7 @@ void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction) } addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT0); - mul32(Imm32(sizeof(Register)), regT2, regT2); + mul32(TrustedImm32(sizeof(Register)), regT2, regT2); subPtr(regT2, regT0); loadPtr(BaseIndex(regT0, regT1, TimesEight, 0), regT0); if (numArgs) @@ -1644,7 +1643,7 @@ void JIT::emitSlow_op_resolve_global_dynamic(Instruction* currentInstruction, Ve while (skip--) linkSlowCase(iter); JITStubCall resolveStubCall(this, cti_op_resolve); - resolveStubCall.addArgument(ImmPtr(ident)); + resolveStubCall.addArgument(TrustedImmPtr(ident)); resolveStubCall.call(dst); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_resolve_global_dynamic)); @@ -1652,7 +1651,7 @@ void JIT::emitSlow_op_resolve_global_dynamic(Instruction* currentInstruction, Ve linkSlowCase(iter); // We managed to skip all the nodes in the scope chain, but the cache missed. JITStubCall stubCall(this, cti_op_resolve_global); - stubCall.addArgument(ImmPtr(ident)); + stubCall.addArgument(TrustedImmPtr(ident)); stubCall.addArgument(Imm32(currentIndex)); stubCall.addArgument(regT0); stubCall.call(dst); @@ -1661,7 +1660,7 @@ void JIT::emitSlow_op_resolve_global_dynamic(Instruction* currentInstruction, Ve void JIT::emit_op_new_regexp(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_new_regexp); - stubCall.addArgument(ImmPtr(m_codeBlock->regexp(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(m_codeBlock->regexp(currentInstruction[2].u.operand))); stubCall.call(currentInstruction[1].u.operand); } @@ -1685,26 +1684,27 @@ void JIT::emit_op_load_varargs(Instruction* currentInstruction) } #if USE(JSVALUE32_64) - addSlowCase(branch32(NotEqual, tagFor(argsOffset), Imm32(JSValue::EmptyValueTag))); + addSlowCase(branch32(NotEqual, tagFor(argsOffset), TrustedImm32(JSValue::EmptyValueTag))); #else addSlowCase(branchTestPtr(NonZero, addressFor(argsOffset))); #endif // Load arg count into regT0 emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0); - storePtr(regT0, addressFor(argCountDst)); - Jump endBranch = branch32(Equal, regT0, Imm32(1)); + store32(TrustedImm32(Int32Tag), intTagFor(argCountDst)); + store32(regT0, intPayloadFor(argCountDst)); + Jump endBranch = branch32(Equal, regT0, TrustedImm32(1)); - mul32(Imm32(sizeof(Register)), regT0, regT3); - addPtr(Imm32(static_cast<unsigned>(sizeof(Register) - RegisterFile::CallFrameHeaderSize * sizeof(Register))), callFrameRegister, regT1); + mul32(TrustedImm32(sizeof(Register)), regT0, regT3); + addPtr(TrustedImm32(static_cast<unsigned>(sizeof(Register) - RegisterFile::CallFrameHeaderSize * sizeof(Register))), callFrameRegister, regT1); subPtr(regT3, regT1); // regT1 is now the start of the out of line arguments addPtr(Imm32(argsOffset * sizeof(Register)), callFrameRegister, regT2); // regT2 is the target buffer // Bounds check the registerfile addPtr(regT2, regT3); addPtr(Imm32((registerOffset - argsOffset) * sizeof(Register)), regT3); - addSlowCase(branchPtr(Below, AbsoluteAddress(&m_globalData->interpreter->registerFile().m_end), regT3)); + addSlowCase(branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT3)); - sub32(Imm32(1), regT0); + sub32(TrustedImm32(1), regT0); Label loopStart = label(); loadPtr(BaseIndex(regT1, regT0, TimesEight, static_cast<unsigned>(0 - 2 * sizeof(Register))), regT3); storePtr(regT3, BaseIndex(regT2, regT0, TimesEight, static_cast<unsigned>(0 - sizeof(Register)))); @@ -1712,7 +1712,7 @@ void JIT::emit_op_load_varargs(Instruction* currentInstruction) loadPtr(BaseIndex(regT1, regT0, TimesEight, static_cast<unsigned>(sizeof(void*) - 2 * sizeof(Register))), regT3); storePtr(regT3, BaseIndex(regT2, regT0, TimesEight, static_cast<unsigned>(sizeof(void*) - sizeof(Register)))); #endif - branchSubPtr(NonZero, Imm32(1), regT0).linkTo(loopStart, this); + branchSubPtr(NonZero, TrustedImm32(1), regT0).linkTo(loopStart, this); endBranch.link(this); } @@ -1729,8 +1729,9 @@ void JIT::emitSlow_op_load_varargs(Instruction* currentInstruction, Vector<SlowC JITStubCall stubCall(this, cti_op_load_varargs); stubCall.addArgument(Imm32(argsOffset)); stubCall.call(); - // Stores a naked int32 in the register file. - store32(returnValueRegister, Address(callFrameRegister, argCountDst * sizeof(Register))); + + store32(TrustedImm32(Int32Tag), intTagFor(argCountDst)); + store32(returnValueRegister, intPayloadFor(argCountDst)); } void JIT::emit_op_new_func(Instruction* currentInstruction) @@ -1739,13 +1740,13 @@ void JIT::emit_op_new_func(Instruction* currentInstruction) int dst = currentInstruction[1].u.operand; if (currentInstruction[3].u.operand) { #if USE(JSVALUE32_64) - lazyJump = branch32(NotEqual, tagFor(dst), Imm32(JSValue::EmptyValueTag)); + lazyJump = branch32(NotEqual, tagFor(dst), TrustedImm32(JSValue::EmptyValueTag)); #else lazyJump = branchTestPtr(NonZero, addressFor(dst)); #endif } JITStubCall stubCall(this, cti_op_new_func); - stubCall.addArgument(ImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand))); stubCall.call(currentInstruction[1].u.operand); if (currentInstruction[3].u.operand) lazyJump.link(this); diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp index 0c8402b..bc0b2cb 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp @@ -52,15 +52,15 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable // regT0 holds payload, regT1 holds tag - Jump string_failureCases1 = branch32(NotEqual, regT1, Imm32(JSValue::CellTag)); - Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)); + Jump string_failureCases1 = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); + Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)); // Checks out okay! - get the length from the Ustring. load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_length)), regT2); - Jump string_failureCases3 = branch32(Above, regT2, Imm32(INT_MAX)); + Jump string_failureCases3 = branch32(Above, regT2, TrustedImm32(INT_MAX)); move(regT2, regT0); - move(Imm32(JSValue::Int32Tag), regT1); + move(TrustedImm32(JSValue::Int32Tag), regT1); ret(); #endif @@ -103,7 +103,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); - Jump hasCodeBlock3 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForCall)), Imm32(0)); + Jump hasCodeBlock3 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForCall)), TrustedImm32(0)); preserveReturnAddressAfterCall(regT3); restoreArgumentReference(); Call callCompileCall = call(); @@ -123,7 +123,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2); - Jump hasCodeBlock4 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForConstruct)), Imm32(0)); + Jump hasCodeBlock4 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForConstruct)), TrustedImm32(0)); preserveReturnAddressAfterCall(regT3); restoreArgumentReference(); Call callCompileCconstruct = call(); @@ -142,10 +142,10 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1); emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); restoreReturnAddressBeforeReturn(regT1); - move(ImmPtr(&globalData->exceptionLocation), regT2); + move(TrustedImmPtr(&globalData->exceptionLocation), regT2); storePtr(regT1, regT2); poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); - poke(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value())); + poke(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value())); ret(); // NativeCall Trampoline @@ -205,7 +205,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon // get to its global data. emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0); emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0); - emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); peek(regT1); emitPutToCallFrameHeader(regT1, RegisterFile::ReturnPC); @@ -214,7 +214,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon // Host function signature: f(ExecState*); move(callFrameRegister, X86Registers::ecx); - subPtr(Imm32(16 - sizeof(void*)), stackPointerRegister); // Align stack after call. + subPtr(TrustedImm32(16 - sizeof(void*)), stackPointerRegister); // Align stack after call. // call the function emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT1); @@ -222,14 +222,14 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon move(regT0, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack. call(Address(regT1, executableOffsetToFunction)); - addPtr(Imm32(16 - sizeof(void*)), stackPointerRegister); + addPtr(TrustedImm32(16 - sizeof(void*)), stackPointerRegister); #elif CPU(ARM) // Load caller frame's scope chain into this callframe so that whatever we call can // get to its global data. emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2); emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2); - emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); preserveReturnAddressAfterCall(regT3); // Callee preserved emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); @@ -251,7 +251,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon // get to its global data. emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0); emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0); - emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); preserveReturnAddressAfterCall(regT3); // Callee preserved emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); @@ -261,7 +261,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon // Allocate stack space for 16 bytes (8-byte aligned) // 16 bytes (unused) for 4 arguments - subPtr(Imm32(16), stackPointerRegister); + subPtr(TrustedImm32(16), stackPointerRegister); // Setup arg0 move(callFrameRegister, MIPSRegisters::a0); @@ -273,7 +273,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon call(Address(regT2, executableOffsetToFunction)); // Restore stack space - addPtr(Imm32(16), stackPointerRegister); + addPtr(TrustedImm32(16), stackPointerRegister); restoreReturnAddressBeforeReturn(regT3); @@ -285,7 +285,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon #endif // CPU(X86) // Check for an exception - Jump sawException = branch32(NotEqual, AbsoluteAddress(reinterpret_cast<char*>(&globalData->exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), Imm32(JSValue::EmptyValueTag)); + Jump sawException = branch32(NotEqual, AbsoluteAddress(reinterpret_cast<char*>(&globalData->exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)); // Return. ret(); @@ -296,12 +296,12 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon // Grab the return address. preserveReturnAddressAfterCall(regT1); - move(ImmPtr(&globalData->exceptionLocation), regT2); + move(TrustedImmPtr(&globalData->exceptionLocation), regT2); storePtr(regT1, regT2); poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); // Set the return address. - move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1); + move(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1); restoreReturnAddressBeforeReturn(regT1); ret(); @@ -321,7 +321,7 @@ JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executa // get to its global data. emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0); emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0); - emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); peek(regT1); emitPutToCallFrameHeader(regT1, RegisterFile::ReturnPC); @@ -330,21 +330,21 @@ JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executa // Host function signature: f(ExecState*); move(callFrameRegister, X86Registers::ecx); - subPtr(Imm32(16 - sizeof(void*)), stackPointerRegister); // Align stack after call. + subPtr(TrustedImm32(16 - sizeof(void*)), stackPointerRegister); // Align stack after call. move(regT0, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack. // call the function nativeCall = call(); - addPtr(Imm32(16 - sizeof(void*)), stackPointerRegister); + addPtr(TrustedImm32(16 - sizeof(void*)), stackPointerRegister); #elif CPU(ARM) // Load caller frame's scope chain into this callframe so that whatever we call can // get to its global data. emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2); emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2); - emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); preserveReturnAddressAfterCall(regT3); // Callee preserved emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); @@ -367,7 +367,7 @@ JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executa // get to its global data. emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0); emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0); - emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain); + emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain); preserveReturnAddressAfterCall(regT3); // Callee preserved emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC); @@ -377,7 +377,7 @@ JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executa // Allocate stack space for 16 bytes (8-byte aligned) // 16 bytes (unused) for 4 arguments - subPtr(Imm32(16), stackPointerRegister); + subPtr(TrustedImm32(16), stackPointerRegister); // Setup arg0 move(callFrameRegister, MIPSRegisters::a0); @@ -391,7 +391,7 @@ JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executa nativeCall = call(); // Restore stack space - addPtr(Imm32(16), stackPointerRegister); + addPtr(TrustedImm32(16), stackPointerRegister); restoreReturnAddressBeforeReturn(regT3); @@ -402,7 +402,7 @@ JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executa #endif // CPU(X86) // Check for an exception - Jump sawException = branch32(NotEqual, AbsoluteAddress(reinterpret_cast<char*>(&globalData->exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), Imm32(JSValue::EmptyValueTag)); + Jump sawException = branch32(NotEqual, AbsoluteAddress(reinterpret_cast<char*>(&globalData->exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)); // Return. ret(); @@ -413,12 +413,12 @@ JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executa // Grab the return address. preserveReturnAddressAfterCall(regT1); - move(ImmPtr(&globalData->exceptionLocation), regT2); + move(TrustedImmPtr(&globalData->exceptionLocation), regT2); storePtr(regT1, regT2); poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*)); // Set the return address. - move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1); + move(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1); restoreReturnAddressBeforeReturn(regT1); ret(); @@ -470,21 +470,21 @@ void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction) if (isOperandConstantImmediateInt(op1)) { emitLoad(op2, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op1).asInt32())), target); return; } if (isOperandConstantImmediateInt(op2)) { emitLoad(op1, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); addJump(branch32(LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target); return; } emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); addJump(branch32(LessThanOrEqual, regT0, regT2), target); } @@ -520,8 +520,8 @@ void JIT::emit_op_check_has_instance(Instruction* currentInstruction) emitJumpSlowCaseIfNotJSCell(baseVal); // Check that baseVal 'ImplementsHasInstance'. - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0); - addSlowCase(branchTest8(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsHasInstance))); + loadPtr(Address(regT0, JSCell::structureOffset()), regT0); + addSlowCase(branchTest8(Zero, Address(regT0, Structure::typeInfoFlagsOffset()), TrustedImm32(ImplementsHasInstance))); } void JIT::emit_op_instanceof(Instruction* currentInstruction) @@ -542,29 +542,29 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction) emitJumpSlowCaseIfNotJSCell(proto); // Check that prototype is an object - loadPtr(Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), regT3); - addSlowCase(branch8(NotEqual, Address(regT3, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); + loadPtr(Address(regT1, JSCell::structureOffset()), regT3); + addSlowCase(branch8(NotEqual, Address(regT3, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType))); // Fixme: this check is only needed because the JSC API allows HasInstance to be overridden; we should deprecate this. // Check that baseVal 'ImplementsDefaultHasInstance'. - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0); - addSlowCase(branchTest8(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance))); + loadPtr(Address(regT0, JSCell::structureOffset()), regT0); + addSlowCase(branchTest8(Zero, Address(regT0, Structure::typeInfoFlagsOffset()), TrustedImm32(ImplementsDefaultHasInstance))); // Optimistically load the result true, and start looping. // Initially, regT1 still contains proto and regT2 still contains value. // As we loop regT2 will be updated with its prototype, recursively walking the prototype chain. - move(Imm32(JSValue::TrueTag), regT0); + move(TrustedImm32(JSValue::TrueTag), regT0); Label loop(this); // Load the prototype of the cell in regT2. If this is equal to regT1 - WIN! // Otherwise, check if we've hit null - if we have then drop out of the loop, if not go again. - loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - load32(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2); + loadPtr(Address(regT2, JSCell::structureOffset()), regT2); + load32(Address(regT2, Structure::prototypeOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2); Jump isInstance = branchPtr(Equal, regT2, regT1); branchTest32(NonZero, regT2).linkTo(loop, this); // We get here either by dropping out of the loop, or if value was not an Object. Result is false. - move(Imm32(JSValue::FalseTag), regT0); + move(TrustedImm32(JSValue::FalseTag), regT0); // isInstance jumps right down to here, to skip setting the result to false (it has already set true). isInstance.link(this); @@ -609,7 +609,7 @@ void JIT::emit_op_get_global_var(Instruction* currentInstruction) ASSERT(globalObject->isGlobalObject()); int index = currentInstruction[2].u.operand; - loadPtr(&globalObject->d()->registers, regT2); + loadPtr(&globalObject->m_registers, regT2); emitLoad(index, regT1, regT0, regT2); emitStore(dst, regT1, regT0); @@ -625,7 +625,7 @@ void JIT::emit_op_put_global_var(Instruction* currentInstruction) emitLoad(value, regT1, regT0); - loadPtr(&globalObject->d()->registers, regT2); + loadPtr(&globalObject->m_registers, regT2); emitStore(index, regT1, regT0, regT2); map(m_bytecodeOffset + OPCODE_LENGTH(op_put_global_var), value, regT1, regT0); } @@ -642,7 +642,7 @@ void JIT::emit_op_get_scoped_var(Instruction* currentInstruction) if (checkTopLevel && skip--) { Jump activationNotCreated; if (checkTopLevel) - activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag)); + activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), TrustedImm32(JSValue::EmptyValueTag)); loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2); activationNotCreated.link(this); } @@ -650,8 +650,7 @@ void JIT::emit_op_get_scoped_var(Instruction* currentInstruction) loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2); loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2); - loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, d)), regT2); - loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), regT2); + loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT2); emitLoad(index, regT1, regT0, regT2); emitStore(dst, regT1, regT0); @@ -672,7 +671,7 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction) if (checkTopLevel && skip--) { Jump activationNotCreated; if (checkTopLevel) - activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag)); + activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), TrustedImm32(JSValue::EmptyValueTag)); loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2); activationNotCreated.link(this); } @@ -680,8 +679,7 @@ void JIT::emit_op_put_scoped_var(Instruction* currentInstruction) loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2); loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2); - loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, d)), regT2); - loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), regT2); + loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT2); emitStore(index, regT1, regT0, regT2); map(m_bytecodeOffset + OPCODE_LENGTH(op_put_scoped_var), value, regT1, regT0); @@ -691,8 +689,8 @@ void JIT::emit_op_tear_off_activation(Instruction* currentInstruction) { unsigned activation = currentInstruction[1].u.operand; unsigned arguments = currentInstruction[2].u.operand; - Jump activationCreated = branch32(NotEqual, tagFor(activation), Imm32(JSValue::EmptyValueTag)); - Jump argumentsNotCreated = branch32(Equal, tagFor(arguments), Imm32(JSValue::EmptyValueTag)); + Jump activationCreated = branch32(NotEqual, tagFor(activation), TrustedImm32(JSValue::EmptyValueTag)); + Jump argumentsNotCreated = branch32(Equal, tagFor(arguments), TrustedImm32(JSValue::EmptyValueTag)); activationCreated.link(this); JITStubCall stubCall(this, cti_op_tear_off_activation); stubCall.addArgument(currentInstruction[1].u.operand); @@ -705,7 +703,7 @@ void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction) { int dst = currentInstruction[1].u.operand; - Jump argsNotCreated = branch32(Equal, tagFor(unmodifiedArgumentsRegister(dst)), Imm32(JSValue::EmptyValueTag)); + Jump argsNotCreated = branch32(Equal, tagFor(unmodifiedArgumentsRegister(dst)), TrustedImm32(JSValue::EmptyValueTag)); JITStubCall stubCall(this, cti_op_tear_off_arguments); stubCall.addArgument(unmodifiedArgumentsRegister(dst)); stubCall.call(); @@ -723,7 +721,7 @@ void JIT::emit_op_new_array(Instruction* currentInstruction) void JIT::emit_op_resolve(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.call(currentInstruction[1].u.operand); } @@ -734,8 +732,8 @@ void JIT::emit_op_to_primitive(Instruction* currentInstruction) emitLoad(src, regT1, regT0); - Jump isImm = branch32(NotEqual, regT1, Imm32(JSValue::CellTag)); - addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr))); + Jump isImm = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); + addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr))); isImm.link(this); if (dst != src) @@ -765,7 +763,7 @@ void JIT::emit_op_strcat(Instruction* currentInstruction) void JIT::emit_op_resolve_base(Instruction* currentInstruction) { JITStubCall stubCall(this, currentInstruction[3].u.operand ? cti_op_resolve_base_strict_put : cti_op_resolve_base); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.call(currentInstruction[1].u.operand); } @@ -773,14 +771,14 @@ void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_ensure_property_exists); stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.call(currentInstruction[1].u.operand); } void JIT::emit_op_resolve_skip(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve_skip); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); stubCall.call(currentInstruction[1].u.operand); } @@ -797,9 +795,9 @@ void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool dynamic) void* offsetAddr = &(m_codeBlock->globalResolveInfo(currentIndex).offset); // Verify structure. - move(ImmPtr(globalObject), regT0); + move(TrustedImmPtr(globalObject), regT0); loadPtr(structureAddress, regT1); - addSlowCase(branchPtr(NotEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)))); + addSlowCase(branchPtr(NotEqual, regT1, Address(regT0, JSCell::structureOffset()))); // Load property. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_propertyStorage)), regT2); @@ -819,7 +817,7 @@ void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<Slo linkSlowCase(iter); JITStubCall stubCall(this, cti_op_resolve_global); - stubCall.addArgument(ImmPtr(ident)); + stubCall.addArgument(TrustedImmPtr(ident)); stubCall.addArgument(Imm32(currentIndex)); stubCall.call(dst); } @@ -831,9 +829,9 @@ void JIT::emit_op_not(Instruction* currentInstruction) emitLoadTag(src, regT0); - xor32(Imm32(JSValue::FalseTag), regT0); - addSlowCase(branchTest32(NonZero, regT0, Imm32(~1))); - xor32(Imm32(JSValue::TrueTag), regT0); + xor32(TrustedImm32(JSValue::FalseTag), regT0); + addSlowCase(branchTest32(NonZero, regT0, TrustedImm32(~1))); + xor32(TrustedImm32(JSValue::TrueTag), regT0); emitStoreBool(dst, regT0, (dst == src)); } @@ -857,17 +855,17 @@ void JIT::emit_op_jfalse(Instruction* currentInstruction) emitLoad(cond, regT1, regT0); - Jump isTrue = branch32(Equal, regT1, Imm32(JSValue::TrueTag)); - addJump(branch32(Equal, regT1, Imm32(JSValue::FalseTag)), target); + Jump isTrue = branch32(Equal, regT1, TrustedImm32(JSValue::TrueTag)); + addJump(branch32(Equal, regT1, TrustedImm32(JSValue::FalseTag)), target); - Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); - Jump isTrue2 = branch32(NotEqual, regT0, Imm32(0)); + Jump isNotInteger = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)); + Jump isTrue2 = branch32(NotEqual, regT0, TrustedImm32(0)); addJump(jump(), target); if (supportsFloatingPoint()) { isNotInteger.link(this); - addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); + addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag))); emitLoadDouble(cond, fpRegT0); addJump(branchDoubleZeroOrNaN(fpRegT0, fpRegT1), target); @@ -897,17 +895,17 @@ void JIT::emit_op_jtrue(Instruction* currentInstruction) emitLoad(cond, regT1, regT0); - Jump isFalse = branch32(Equal, regT1, Imm32(JSValue::FalseTag)); - addJump(branch32(Equal, regT1, Imm32(JSValue::TrueTag)), target); + Jump isFalse = branch32(Equal, regT1, TrustedImm32(JSValue::FalseTag)); + addJump(branch32(Equal, regT1, TrustedImm32(JSValue::TrueTag)), target); - Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); - Jump isFalse2 = branch32(Equal, regT0, Imm32(0)); + Jump isNotInteger = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)); + Jump isFalse2 = branch32(Equal, regT0, TrustedImm32(0)); addJump(jump(), target); if (supportsFloatingPoint()) { isNotInteger.link(this); - addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag))); + addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag))); emitLoadDouble(cond, fpRegT0); addJump(branchDoubleNonZero(fpRegT0, fpRegT1), target); @@ -937,11 +935,11 @@ void JIT::emit_op_jeq_null(Instruction* currentInstruction) emitLoad(src, regT1, regT0); - Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag)); + Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - addJump(branchTest8(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); + addJump(branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)), target); Jump wasNotImmediate = jump(); @@ -949,7 +947,7 @@ void JIT::emit_op_jeq_null(Instruction* currentInstruction) isImmediate.link(this); ASSERT((JSValue::UndefinedTag + 1 == JSValue::NullTag) && !(JSValue::NullTag + 1)); - addJump(branch32(AboveOrEqual, regT1, Imm32(JSValue::UndefinedTag)), target); + addJump(branch32(AboveOrEqual, regT1, TrustedImm32(JSValue::UndefinedTag)), target); wasNotImmediate.link(this); } @@ -961,11 +959,11 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction) emitLoad(src, regT1, regT0); - Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag)); + Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - addJump(branchTest8(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); + addJump(branchTest8(Zero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)), target); Jump wasNotImmediate = jump(); @@ -973,7 +971,7 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction) isImmediate.link(this); ASSERT((JSValue::UndefinedTag + 1 == JSValue::NullTag) && !(JSValue::NullTag + 1)); - addJump(branch32(Below, regT1, Imm32(JSValue::UndefinedTag)), target); + addJump(branch32(Below, regT1, TrustedImm32(JSValue::UndefinedTag)), target); wasNotImmediate.link(this); } @@ -981,19 +979,19 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction) void JIT::emit_op_jneq_ptr(Instruction* currentInstruction) { unsigned src = currentInstruction[1].u.operand; - JSCell* ptr = currentInstruction[2].u.jsCell; + JSCell* ptr = currentInstruction[2].u.jsCell.get(); unsigned target = currentInstruction[3].u.operand; emitLoad(src, regT1, regT0); - addJump(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)), target); - addJump(branchPtr(NotEqual, regT0, ImmPtr(ptr)), target); + addJump(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)), target); + addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(ptr)), target); } void JIT::emit_op_jsr(Instruction* currentInstruction) { int retAddrDst = currentInstruction[1].u.operand; int target = currentInstruction[2].u.operand; - DataLabelPtr storeLocation = storePtrWithPatch(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst)); + DataLabelPtr storeLocation = storePtrWithPatch(TrustedImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst)); addJump(jump(), target); m_jsrSites.append(JSRInfo(storeLocation, label())); } @@ -1011,11 +1009,11 @@ void JIT::emit_op_eq(Instruction* currentInstruction) emitLoad2(src1, regT1, regT0, src2, regT3, regT2); addSlowCase(branch32(NotEqual, regT1, regT3)); - addSlowCase(branch32(Equal, regT1, Imm32(JSValue::CellTag))); - addSlowCase(branch32(Below, regT1, Imm32(JSValue::LowestTag))); + addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::CellTag))); + addSlowCase(branch32(Below, regT1, TrustedImm32(JSValue::LowestTag))); set8Compare32(Equal, regT0, regT2, regT0); - or32(Imm32(JSValue::FalseTag), regT0); + or32(TrustedImm32(JSValue::FalseTag), regT0); emitStoreBool(dst, regT0); } @@ -1032,8 +1030,8 @@ void JIT::emitSlow_op_eq(Instruction* currentInstruction, Vector<SlowCaseEntry>: genericCase.append(getSlowCase(iter)); // tags not equal linkSlowCase(iter); // tags equal and JSCell - genericCase.append(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr))); - genericCase.append(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsStringVPtr))); + genericCase.append(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr))); + genericCase.append(branchPtr(NotEqual, Address(regT2), TrustedImmPtr(m_globalData->jsStringVPtr))); // String case. JITStubCall stubCallEqStrings(this, cti_op_eq_strings); @@ -1051,7 +1049,7 @@ void JIT::emitSlow_op_eq(Instruction* currentInstruction, Vector<SlowCaseEntry>: stubCallEq.call(regT0); storeResult.link(this); - or32(Imm32(JSValue::FalseTag), regT0); + or32(TrustedImm32(JSValue::FalseTag), regT0); emitStoreBool(dst, regT0); } @@ -1063,11 +1061,11 @@ void JIT::emit_op_neq(Instruction* currentInstruction) emitLoad2(src1, regT1, regT0, src2, regT3, regT2); addSlowCase(branch32(NotEqual, regT1, regT3)); - addSlowCase(branch32(Equal, regT1, Imm32(JSValue::CellTag))); - addSlowCase(branch32(Below, regT1, Imm32(JSValue::LowestTag))); + addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::CellTag))); + addSlowCase(branch32(Below, regT1, TrustedImm32(JSValue::LowestTag))); set8Compare32(NotEqual, regT0, regT2, regT0); - or32(Imm32(JSValue::FalseTag), regT0); + or32(TrustedImm32(JSValue::FalseTag), regT0); emitStoreBool(dst, regT0); } @@ -1082,8 +1080,8 @@ void JIT::emitSlow_op_neq(Instruction* currentInstruction, Vector<SlowCaseEntry> genericCase.append(getSlowCase(iter)); // tags not equal linkSlowCase(iter); // tags equal and JSCell - genericCase.append(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr))); - genericCase.append(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsStringVPtr))); + genericCase.append(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr))); + genericCase.append(branchPtr(NotEqual, Address(regT2), TrustedImmPtr(m_globalData->jsStringVPtr))); // String case. JITStubCall stubCallEqStrings(this, cti_op_eq_strings); @@ -1101,8 +1099,8 @@ void JIT::emitSlow_op_neq(Instruction* currentInstruction, Vector<SlowCaseEntry> stubCallEq.call(regT0); storeResult.link(this); - xor32(Imm32(0x1), regT0); - or32(Imm32(JSValue::FalseTag), regT0); + xor32(TrustedImm32(0x1), regT0); + or32(TrustedImm32(JSValue::FalseTag), regT0); emitStoreBool(dst, regT0); } @@ -1119,15 +1117,15 @@ void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqTy // cells and/or Int32s. move(regT0, regT2); and32(regT1, regT2); - addSlowCase(branch32(Below, regT2, Imm32(JSValue::LowestTag))); - addSlowCase(branch32(AboveOrEqual, regT2, Imm32(JSValue::CellTag))); + addSlowCase(branch32(Below, regT2, TrustedImm32(JSValue::LowestTag))); + addSlowCase(branch32(AboveOrEqual, regT2, TrustedImm32(JSValue::CellTag))); if (type == OpStrictEq) set8Compare32(Equal, regT0, regT1, regT0); else set8Compare32(NotEqual, regT0, regT1, regT0); - or32(Imm32(JSValue::FalseTag), regT0); + or32(TrustedImm32(JSValue::FalseTag), regT0); emitStoreBool(dst, regT0); } @@ -1178,22 +1176,22 @@ void JIT::emit_op_eq_null(Instruction* currentInstruction) unsigned src = currentInstruction[2].u.operand; emitLoad(src, regT1, regT0); - Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag)); + Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1); - set32Test8(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT1); + loadPtr(Address(regT0, JSCell::structureOffset()), regT1); + set32Test8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT1); Jump wasNotImmediate = jump(); isImmediate.link(this); - set8Compare32(Equal, regT1, Imm32(JSValue::NullTag), regT2); - set8Compare32(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1); + set8Compare32(Equal, regT1, TrustedImm32(JSValue::NullTag), regT2); + set8Compare32(Equal, regT1, TrustedImm32(JSValue::UndefinedTag), regT1); or32(regT2, regT1); wasNotImmediate.link(this); - or32(Imm32(JSValue::FalseTag), regT1); + or32(TrustedImm32(JSValue::FalseTag), regT1); emitStoreBool(dst, regT1); } @@ -1204,22 +1202,22 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction) unsigned src = currentInstruction[2].u.operand; emitLoad(src, regT1, regT0); - Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag)); + Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1); - set32Test8(Zero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT1); + loadPtr(Address(regT0, JSCell::structureOffset()), regT1); + set32Test8(Zero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT1); Jump wasNotImmediate = jump(); isImmediate.link(this); - set8Compare32(NotEqual, regT1, Imm32(JSValue::NullTag), regT2); - set8Compare32(NotEqual, regT1, Imm32(JSValue::UndefinedTag), regT1); + set8Compare32(NotEqual, regT1, TrustedImm32(JSValue::NullTag), regT2); + set8Compare32(NotEqual, regT1, TrustedImm32(JSValue::UndefinedTag), regT1); and32(regT2, regT1); wasNotImmediate.link(this); - or32(Imm32(JSValue::FalseTag), regT1); + or32(TrustedImm32(JSValue::FalseTag), regT1); emitStoreBool(dst, regT1); } @@ -1227,7 +1225,7 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction) void JIT::emit_op_resolve_with_base(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve_with_base); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand))); stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); stubCall.call(currentInstruction[2].u.operand); } @@ -1235,7 +1233,7 @@ void JIT::emit_op_resolve_with_base(Instruction* currentInstruction) void JIT::emit_op_new_func_exp(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_new_func_exp); - stubCall.addArgument(ImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand))); stubCall.call(currentInstruction[1].u.operand); } @@ -1265,10 +1263,10 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction) emitLoad(base, regT1, regT0); if (!m_codeBlock->isKnownNotImmediate(base)) - isNotObject.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + isNotObject.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag))); if (base != m_codeBlock->thisRegister() || m_codeBlock->isStrictMode()) { - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - isNotObject.append(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); + isNotObject.append(branch8(NotEqual, Address(regT2, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType))); } // We could inline the case where you have a valid cache, but @@ -1278,13 +1276,15 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction) getPnamesStubCall.addArgument(regT0); getPnamesStubCall.call(dst); load32(Address(regT0, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStringsSize)), regT3); - store32(Imm32(0), addressFor(i)); - store32(regT3, addressFor(size)); + store32(TrustedImm32(Int32Tag), intTagFor(i)); + store32(TrustedImm32(0), intPayloadFor(i)); + store32(TrustedImm32(Int32Tag), intTagFor(size)); + store32(regT3, payloadFor(size)); Jump end = jump(); isNotObject.link(this); - addJump(branch32(Equal, regT1, Imm32(JSValue::NullTag)), breakTarget); - addJump(branch32(Equal, regT1, Imm32(JSValue::UndefinedTag)), breakTarget); + addJump(branch32(Equal, regT1, TrustedImm32(JSValue::NullTag)), breakTarget); + addJump(branch32(Equal, regT1, TrustedImm32(JSValue::UndefinedTag)), breakTarget); JITStubCall toObjectStubCall(this, cti_to_object); toObjectStubCall.addArgument(regT1, regT0); toObjectStubCall.call(base); @@ -1305,25 +1305,25 @@ void JIT::emit_op_next_pname(Instruction* currentInstruction) JumpList callHasProperty; Label begin(this); - load32(addressFor(i), regT0); - Jump end = branch32(Equal, regT0, addressFor(size)); + load32(intPayloadFor(i), regT0); + Jump end = branch32(Equal, regT0, intPayloadFor(size)); // Grab key @ i - loadPtr(addressFor(it), regT1); + loadPtr(payloadFor(it), regT1); loadPtr(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStrings)), regT2); load32(BaseIndex(regT2, regT0, TimesEight), regT2); - store32(Imm32(JSValue::CellTag), tagFor(dst)); + store32(TrustedImm32(JSValue::CellTag), tagFor(dst)); store32(regT2, payloadFor(dst)); // Increment i - add32(Imm32(1), regT0); - store32(regT0, addressFor(i)); + add32(TrustedImm32(1), regT0); + store32(regT0, intPayloadFor(i)); // Verify that i is valid: - loadPtr(addressFor(base), regT0); + loadPtr(payloadFor(base), regT0); // Test base's structure - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); callHasProperty.append(branchPtr(NotEqual, regT2, Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure))))); // Test base's prototype chain @@ -1332,11 +1332,11 @@ void JIT::emit_op_next_pname(Instruction* currentInstruction) addJump(branchTestPtr(Zero, Address(regT3)), target); Label checkPrototype(this); - callHasProperty.append(branch32(Equal, Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), Imm32(JSValue::NullTag))); - loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2); - loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); + callHasProperty.append(branch32(Equal, Address(regT2, Structure::prototypeOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::NullTag))); + loadPtr(Address(regT2, Structure::prototypeOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2); + loadPtr(Address(regT2, JSCell::structureOffset()), regT2); callHasProperty.append(branchPtr(NotEqual, regT2, Address(regT3))); - addPtr(Imm32(sizeof(Structure*)), regT3); + addPtr(TrustedImm32(sizeof(Structure*)), regT3); branchTestPtr(NonZero, Address(regT3)).linkTo(checkPrototype, this); // Continue loop. @@ -1377,8 +1377,8 @@ void JIT::emit_op_to_jsnumber(Instruction* currentInstruction) emitLoad(src, regT1, regT0); - Jump isInt32 = branch32(Equal, regT1, Imm32(JSValue::Int32Tag)); - addSlowCase(branch32(AboveOrEqual, regT1, Imm32(JSValue::EmptyValueTag))); + Jump isInt32 = branch32(Equal, regT1, TrustedImm32(JSValue::Int32Tag)); + addSlowCase(branch32(AboveOrEqual, regT1, TrustedImm32(JSValue::EmptyValueTag))); isInt32.link(this); if (src != dst) @@ -1400,7 +1400,7 @@ void JIT::emitSlow_op_to_jsnumber(Instruction* currentInstruction, Vector<SlowCa void JIT::emit_op_push_new_scope(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_push_new_scope); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.addArgument(currentInstruction[3].u.operand); stubCall.call(currentInstruction[1].u.operand); } @@ -1414,8 +1414,8 @@ void JIT::emit_op_catch(Instruction* currentInstruction) loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(struct JITStackFrame, globalData)), regT3); load32(Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); load32(Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); - store32(Imm32(JSValue().payload()), Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception) + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); - store32(Imm32(JSValue().tag()), Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); + store32(TrustedImm32(JSValue().payload()), Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception) + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); + store32(TrustedImm32(JSValue().tag()), Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); unsigned exception = currentInstruction[1].u.operand; emitStore(exception, regT1, regT0); @@ -1520,7 +1520,7 @@ void JIT::emit_op_create_activation(Instruction* currentInstruction) { unsigned activation = currentInstruction[1].u.operand; - Jump activationCreated = branch32(NotEqual, tagFor(activation), Imm32(JSValue::EmptyValueTag)); + Jump activationCreated = branch32(NotEqual, tagFor(activation), TrustedImm32(JSValue::EmptyValueTag)); JITStubCall(this, cti_op_push_activation).call(activation); activationCreated.link(this); } @@ -1529,7 +1529,7 @@ void JIT::emit_op_create_arguments(Instruction* currentInstruction) { unsigned dst = currentInstruction[1].u.operand; - Jump argsCreated = branch32(NotEqual, tagFor(dst), Imm32(JSValue::EmptyValueTag)); + Jump argsCreated = branch32(NotEqual, tagFor(dst), TrustedImm32(JSValue::EmptyValueTag)); if (m_codeBlock->m_numParameters == 1) JITStubCall(this, cti_op_create_arguments_no_params).call(); @@ -1571,10 +1571,10 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction) emitLoad(thisRegister, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag))); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - addSlowCase(branchTest8(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion))); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); + addSlowCase(branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(NeedsThisConversion))); map(m_bytecodeOffset + OPCODE_LENGTH(op_convert_this), thisRegister, regT1, regT0); } @@ -1585,14 +1585,14 @@ void JIT::emit_op_convert_this_strict(Instruction* currentInstruction) emitLoad(thisRegister, regT1, regT0); - Jump notNull = branch32(NotEqual, regT1, Imm32(JSValue::EmptyValueTag)); + Jump notNull = branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag)); emitStore(thisRegister, jsNull()); Jump setThis = jump(); notNull.link(this); - Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag)); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - Jump notAnObject = branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)); - addSlowCase(branchTest8(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion))); + Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); + Jump notAnObject = branch8(NotEqual, Address(regT2, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType)); + addSlowCase(branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(NeedsThisConversion))); isImmediate.link(this); notAnObject.link(this); setThis.link(this); @@ -1648,9 +1648,9 @@ void JIT::emit_op_get_arguments_length(Instruction* currentInstruction) { int dst = currentInstruction[1].u.operand; int argumentsRegister = currentInstruction[2].u.operand; - addSlowCase(branch32(NotEqual, tagFor(argumentsRegister), Imm32(JSValue::EmptyValueTag))); + addSlowCase(branch32(NotEqual, tagFor(argumentsRegister), TrustedImm32(JSValue::EmptyValueTag))); emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0); - sub32(Imm32(1), regT0); + sub32(TrustedImm32(1), regT0); emitStoreInt32(dst, regT0); } @@ -1663,7 +1663,7 @@ void JIT::emitSlow_op_get_arguments_length(Instruction* currentInstruction, Vect JITStubCall stubCall(this, cti_op_get_by_id_generic); stubCall.addArgument(base); - stubCall.addArgument(ImmPtr(&(m_codeBlock->identifier(ident)))); + stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident)))); stubCall.call(dst); } @@ -1672,10 +1672,10 @@ void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction) int dst = currentInstruction[1].u.operand; int argumentsRegister = currentInstruction[2].u.operand; int property = currentInstruction[3].u.operand; - addSlowCase(branch32(NotEqual, tagFor(argumentsRegister), Imm32(JSValue::EmptyValueTag))); + addSlowCase(branch32(NotEqual, tagFor(argumentsRegister), TrustedImm32(JSValue::EmptyValueTag))); emitLoad(property, regT1, regT2); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - add32(Imm32(1), regT2); + addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); + add32(TrustedImm32(1), regT2); // regT2 now contains the integer index of the argument we want, including this emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT3); addSlowCase(branch32(AboveOrEqual, regT2, regT3)); @@ -1692,7 +1692,7 @@ void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction) } addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT1); - mul32(Imm32(sizeof(Register)), regT3, regT3); + mul32(TrustedImm32(sizeof(Register)), regT3, regT3); subPtr(regT3, regT1); loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); @@ -1734,17 +1734,17 @@ void JIT::softModulo() push(regT3); move(regT2, regT3); move(regT0, regT2); - move(Imm32(0), regT1); + move(TrustedImm32(0), regT1); // Check for negative result reminder - Jump positiveRegT3 = branch32(GreaterThanOrEqual, regT3, Imm32(0)); + Jump positiveRegT3 = branch32(GreaterThanOrEqual, regT3, TrustedImm32(0)); neg32(regT3); - xor32(Imm32(1), regT1); + xor32(TrustedImm32(1), regT1); positiveRegT3.link(this); - Jump positiveRegT2 = branch32(GreaterThanOrEqual, regT2, Imm32(0)); + Jump positiveRegT2 = branch32(GreaterThanOrEqual, regT2, TrustedImm32(0)); neg32(regT2); - xor32(Imm32(2), regT1); + xor32(TrustedImm32(2), regT1); positiveRegT2.link(this); // Save the condition for negative reminder @@ -1754,7 +1754,7 @@ void JIT::softModulo() // Power of two fast case move(regT3, regT0); - sub32(Imm32(1), regT0); + sub32(TrustedImm32(1), regT0); Jump powerOfTwo = branchTest32(NotEqual, regT0, regT3); and32(regT0, regT2); powerOfTwo.link(this); @@ -1767,10 +1767,10 @@ void JIT::softModulo() countLeadingZeros32(regT3, regT1); sub32(regT0, regT1); - Jump useFullTable = branch32(Equal, regT1, Imm32(31)); + Jump useFullTable = branch32(Equal, regT1, TrustedImm32(31)); neg32(regT1); - add32(Imm32(31), regT1); + add32(TrustedImm32(31), regT1); int elementSizeByShift = -1; #if CPU(ARM) @@ -1805,7 +1805,7 @@ void JIT::softModulo() // Check for negative reminder pop(regT1); - Jump positiveResult = branch32(Equal, regT1, Imm32(0)); + Jump positiveResult = branch32(Equal, regT1, TrustedImm32(0)); neg32(regT2); positiveResult.link(this); diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp index b497319..68f8dda 100644 --- a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp +++ b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp @@ -54,7 +54,7 @@ JIT::CodePtr JIT::stringGetByValStubGenerator(JSGlobalData* globalData, Executab { JSInterfaceJIT jit; JumpList failures; - failures.append(jit.branchPtr(NotEqual, Address(regT0), ImmPtr(globalData->jsStringVPtr))); + failures.append(jit.branchPtr(NotEqual, Address(regT0), TrustedImmPtr(globalData->jsStringVPtr))); failures.append(jit.branchTest32(NonZero, Address(regT0, OBJECT_OFFSETOF(JSString, m_fiberCount)))); // Load string length to regT1, and start the process of loading the data pointer into regT0 @@ -68,13 +68,13 @@ JIT::CodePtr JIT::stringGetByValStubGenerator(JSGlobalData* globalData, Executab // Load the character jit.load16(BaseIndex(regT0, regT1, TimesTwo, 0), regT0); - failures.append(jit.branch32(AboveOrEqual, regT0, Imm32(0x100))); - jit.move(ImmPtr(globalData->smallStrings.singleCharacterStrings()), regT1); + failures.append(jit.branch32(AboveOrEqual, regT0, TrustedImm32(0x100))); + jit.move(TrustedImmPtr(globalData->smallStrings.singleCharacterStrings()), regT1); jit.loadPtr(BaseIndex(regT1, regT0, ScalePtr, 0), regT0); jit.ret(); failures.link(&jit); - jit.move(Imm32(0), regT0); + jit.move(TrustedImm32(0), regT0); jit.ret(); LinkBuffer patchBuffer(&jit, pool, 0); @@ -99,10 +99,10 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction) zeroExtend32ToPtr(regT1, regT1); emitJumpSlowCaseIfNotJSCell(regT0, base); - addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr))); + addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr))); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2); - addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSArray, m_vectorLength)))); + loadPtr(Address(regT0, JSArray::storageOffset()), regT2); + addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, JSArray::vectorLengthOffset()))); loadPtr(BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0); addSlowCase(branchTestPtr(Zero, regT0)); @@ -120,7 +120,7 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas linkSlowCaseIfNotJSCell(iter, base); // base cell check Jump nonCell = jump(); linkSlowCase(iter); // base array check - Jump notString = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)); + Jump notString = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)); emitNakedCall(m_globalData->getCTIStub(stringGetByValStubGenerator)); Jump failed = branchTestPtr(Zero, regT0); emitPutVirtualRegister(dst, regT0); @@ -159,10 +159,10 @@ void JIT::emit_op_get_by_pname(Instruction* currentInstruction) emitJumpSlowCaseIfNotJSCell(regT0, base); // Test base's structure - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); + loadPtr(Address(regT0, JSCell::structureOffset()), regT2); addSlowCase(branchPtr(NotEqual, regT2, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure)))); load32(addressFor(i), regT3); - sub32(Imm32(1), regT3); + sub32(TrustedImm32(1), regT3); addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots)))); compileGetDirectOffset(regT0, regT0, regT3, regT1); @@ -197,10 +197,10 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction) // See comment in op_get_by_val. zeroExtend32ToPtr(regT1, regT1); emitJumpSlowCaseIfNotJSCell(regT0, base); - addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr))); - addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSArray, m_vectorLength)))); + addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr))); + addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, JSArray::vectorLengthOffset()))); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2); + loadPtr(Address(regT0, JSArray::storageOffset()), regT2); Jump empty = branchTestPtr(Zero, BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); Label storeResult(this); @@ -209,11 +209,11 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction) Jump end = jump(); empty.link(this); - add32(Imm32(1), Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); + add32(TrustedImm32(1), Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); branch32(Below, regT1, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length))).linkTo(storeResult, this); move(regT1, regT0); - add32(Imm32(1), regT0); + add32(TrustedImm32(1), regT0); store32(regT0, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length))); jump().linkTo(storeResult, this); @@ -224,7 +224,7 @@ void JIT::emit_op_put_by_index(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_put_by_index); stubCall.addArgument(currentInstruction[1].u.operand, regT2); - stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); + stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand)); stubCall.addArgument(currentInstruction[3].u.operand, regT2); stubCall.call(); } @@ -233,7 +233,7 @@ void JIT::emit_op_put_getter(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_put_getter); stubCall.addArgument(currentInstruction[1].u.operand, regT2); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.addArgument(currentInstruction[3].u.operand, regT2); stubCall.call(); } @@ -242,7 +242,7 @@ void JIT::emit_op_put_setter(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_put_setter); stubCall.addArgument(currentInstruction[1].u.operand, regT2); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand))); stubCall.addArgument(currentInstruction[3].u.operand, regT2); stubCall.call(); } @@ -251,7 +251,7 @@ void JIT::emit_op_del_by_id(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_del_by_id); stubCall.addArgument(currentInstruction[2].u.operand, regT2); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand))); stubCall.call(currentInstruction[1].u.operand); } @@ -276,7 +276,7 @@ void JIT::emit_op_get_by_id(Instruction* currentInstruction) emitGetVirtualRegister(baseVReg, regT0); JITStubCall stubCall(this, cti_op_get_by_id_generic); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(ident)); + stubCall.addArgument(TrustedImmPtr(ident)); stubCall.call(resultVReg); m_propertyAccessInstructionIndex++; @@ -298,7 +298,7 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction) JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct_generic, cti_op_put_by_id_generic); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(ident)); + stubCall.addArgument(TrustedImmPtr(ident)); stubCall.addArgument(regT1); stubCall.call(); @@ -336,12 +336,12 @@ void JIT::emit_op_method_check(Instruction* currentInstruction) BEGIN_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck); - Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), info.structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); - DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(ImmPtr(0), regT1); - Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), protoStructureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); + Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), info.structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); + DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(TrustedImmPtr(0), regT1); + Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT1, JSCell::structureOffset()), protoStructureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); // This will be relinked to load the function without doing a load. - DataLabelPtr putFunction = moveWithPatch(ImmPtr(0), regT0); + DataLabelPtr putFunction = moveWithPatch(TrustedImmPtr(0), regT0); END_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck); @@ -414,7 +414,7 @@ void JIT::compileGetByIdHotPath(int, int baseVReg, Identifier*, unsigned propert m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin; DataLabelPtr structureToCompare; - Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); + Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); addSlowCase(structureCheck); ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetGetByIdStructure); ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureCheck), patchOffsetGetByIdBranchToSlowCase) @@ -457,7 +457,7 @@ void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident #endif JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(ident)); + stubCall.addArgument(TrustedImmPtr(ident)); Call call = stubCall.call(resultVReg); END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase); @@ -492,7 +492,7 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction) // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over. DataLabelPtr structureToCompare; - addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)))); + addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)))); ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT0); @@ -516,7 +516,7 @@ void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCase JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct : cti_op_put_by_id); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(ident)); + stubCall.addArgument(TrustedImmPtr(ident)); stubCall.addArgument(regT1); Call call = stubCall.call(); @@ -564,10 +564,10 @@ void JIT::testPrototype(JSValue prototype, JumpList& failureCases) // values. In the non X86_64 case, the generated code is slightly more efficient because it uses // two less instructions and doesn't require any scratch registers. #if CPU(X86_64) - move(ImmPtr(prototype.asCell()->structure()), regT3); - failureCases.append(branchPtr(NotEqual, AbsoluteAddress(&prototype.asCell()->m_structure), regT3)); + move(TrustedImmPtr(prototype.asCell()->structure()), regT3); + failureCases.append(branchPtr(NotEqual, AbsoluteAddress(prototype.asCell()->addressOfStructure()), regT3)); #else - failureCases.append(branchPtr(NotEqual, AbsoluteAddress(&prototype.asCell()->m_structure), ImmPtr(prototype.asCell()->structure()))); + failureCases.append(branchPtr(NotEqual, AbsoluteAddress(prototype.asCell()->addressOfStructure()), TrustedImmPtr(prototype.asCell()->structure()))); #endif } @@ -576,7 +576,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure JumpList failureCases; // Check eax is an object of the right Structure. failureCases.append(emitJumpIfNotJSCell(regT0)); - failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure))); + failureCases.append(branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(oldStructure))); testPrototype(oldStructure->storedPrototype(), failureCases); // ecx = baseObject->m_structure @@ -598,8 +598,8 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure stubCall.skipArgument(); // base stubCall.skipArgument(); // ident stubCall.skipArgument(); // value - stubCall.addArgument(Imm32(oldStructure->propertyStorageCapacity())); - stubCall.addArgument(Imm32(newStructure->propertyStorageCapacity())); + stubCall.addArgument(TrustedImm32(oldStructure->propertyStorageCapacity())); + stubCall.addArgument(TrustedImm32(newStructure->propertyStorageCapacity())); stubCall.call(regT0); emitGetJITStubArg(2, regT1); @@ -608,9 +608,9 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure // Assumes m_refCount can be decremented easily, refcount decrement is safe as // codeblock should ensure oldStructure->m_refCount > 0 - sub32(Imm32(1), AbsoluteAddress(oldStructure->addressOfCount())); - add32(Imm32(1), AbsoluteAddress(newStructure->addressOfCount())); - storePtr(ImmPtr(newStructure), Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure))); + sub32(TrustedImm32(1), AbsoluteAddress(oldStructure->addressOfCount())); + add32(TrustedImm32(1), AbsoluteAddress(newStructure->addressOfCount())); + storePtr(TrustedImmPtr(newStructure), Address(regT0, JSCell::structureOffset())); // write the value compilePutDirectOffset(regT0, regT1, newStructure, cachedOffset); @@ -692,12 +692,12 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress) StructureStubInfo* stubInfo = &m_codeBlock->getStubInfo(returnAddress); // Check eax is an array - Jump failureCases1 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)); + Jump failureCases1 = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)); // Checks out okay! - get the length from the storage - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT3); + loadPtr(Address(regT0, JSArray::storageOffset()), regT3); load32(Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_length)), regT2); - Jump failureCases2 = branch32(Above, regT2, Imm32(JSImmediate::maxImmediateInt)); + Jump failureCases2 = branch32(Above, regT2, TrustedImm32(JSImmediate::maxImmediateInt)); emitFastArithIntToImmNoCheck(regT2, regT0); Jump success = jump(); @@ -735,12 +735,12 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str Jump failureCases1 = checkStructure(regT0, structure); // Check the prototype object's Structure had not changed. - Structure** prototypeStructureAddress = &(protoObject->m_structure); + Structure* const * prototypeStructureAddress = protoObject->addressOfStructure(); #if CPU(X86_64) - move(ImmPtr(prototypeStructure), regT3); + move(TrustedImmPtr(prototypeStructure), regT3); Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3); #else - Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure)); + Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), TrustedImmPtr(prototypeStructure)); #endif bool needsStubLink = false; @@ -752,15 +752,15 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); stubCall.addArgument(regT1); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else if (slot.cachedPropertyType() == PropertySlot::Custom) { needsStubLink = true; JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); - stubCall.addArgument(ImmPtr(protoObject)); - stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); - stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(protoObject)); + stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else compileGetDirectOffset(protoObject, regT0, cachedOffset); @@ -804,15 +804,15 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); stubCall.addArgument(regT1); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else if (slot.cachedPropertyType() == PropertySlot::Custom) { needsStubLink = true; JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); - stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else compileGetDirectOffset(regT0, regT0, structure, cachedOffset); @@ -858,12 +858,12 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi Jump failureCases1 = checkStructure(regT0, structure); // Check the prototype object's Structure had not changed. - Structure** prototypeStructureAddress = &(protoObject->m_structure); + Structure* const * prototypeStructureAddress = protoObject->addressOfStructure(); #if CPU(X86_64) - move(ImmPtr(prototypeStructure), regT3); + move(TrustedImmPtr(prototypeStructure), regT3); Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3); #else - Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure)); + Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), TrustedImmPtr(prototypeStructure)); #endif // Checks out okay! @@ -874,15 +874,15 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); stubCall.addArgument(regT1); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else if (slot.cachedPropertyType() == PropertySlot::Custom) { needsStubLink = true; JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); - stubCall.addArgument(ImmPtr(protoObject)); - stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); - stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(protoObject)); + stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else compileGetDirectOffset(protoObject, regT0, cachedOffset); @@ -944,15 +944,15 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); stubCall.addArgument(regT1); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else if (slot.cachedPropertyType() == PropertySlot::Custom) { needsStubLink = true; JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); - stubCall.addArgument(ImmPtr(protoObject)); - stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); - stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(protoObject)); + stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else compileGetDirectOffset(protoObject, regT0, cachedOffset); @@ -979,8 +979,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi // Track the stub we have created so that it will be deleted later. structure->ref(); - chain->ref(); - prototypeStructures->list[currentIndex].set(entryLabel, structure, chain); + prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), entryLabel, structure, chain); // Finally patch the jump to slow case back in the hot path to jump here instead. CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); @@ -1014,15 +1013,15 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); stubCall.addArgument(regT1); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else if (slot.cachedPropertyType() == PropertySlot::Custom) { needsStubLink = true; JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); - stubCall.addArgument(ImmPtr(protoObject)); - stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); - stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(protoObject)); + stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else compileGetDirectOffset(protoObject, regT0, cachedOffset); diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp index 3562200..2a47e5c 100644 --- a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp +++ b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp @@ -70,7 +70,7 @@ void JIT::emit_op_put_getter(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_put_getter); stubCall.addArgument(base); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(property))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(property))); stubCall.addArgument(function); stubCall.call(); } @@ -83,7 +83,7 @@ void JIT::emit_op_put_setter(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_put_setter); stubCall.addArgument(base); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(property))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(property))); stubCall.addArgument(function); stubCall.call(); } @@ -96,7 +96,7 @@ void JIT::emit_op_del_by_id(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_del_by_id); stubCall.addArgument(base); - stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(property))); + stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(property))); stubCall.call(dst); } @@ -155,7 +155,7 @@ void JIT::emit_op_get_by_id(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_get_by_id_generic); stubCall.addArgument(base); - stubCall.addArgument(ImmPtr(&(m_codeBlock->identifier(ident)))); + stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident)))); stubCall.call(dst); m_propertyAccessInstructionIndex++; @@ -175,7 +175,7 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_put_by_id_generic); stubCall.addArgument(base); - stubCall.addArgument(ImmPtr(&(m_codeBlock->identifier(ident)))); + stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident)))); stubCall.addArgument(value); stubCall.call(); @@ -213,16 +213,16 @@ void JIT::emit_op_method_check(Instruction* currentInstruction) BEGIN_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck); - Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), info.structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); - DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(ImmPtr(0), regT2); - Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), protoStructureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); + Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), info.structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); + DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(TrustedImmPtr(0), regT2); + Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT2, JSCell::structureOffset()), protoStructureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); // This will be relinked to load the function without doing a load. - DataLabelPtr putFunction = moveWithPatch(ImmPtr(0), regT0); + DataLabelPtr putFunction = moveWithPatch(TrustedImmPtr(0), regT0); END_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck); - move(Imm32(JSValue::CellTag), regT1); + move(TrustedImm32(JSValue::CellTag), regT1); Jump match = jump(); ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, protoObj), patchOffsetMethodCheckProtoObj); @@ -271,7 +271,7 @@ JIT::CodePtr JIT::stringGetByValStubGenerator(JSGlobalData* globalData, Executab { JSInterfaceJIT jit; JumpList failures; - failures.append(jit.branchPtr(NotEqual, Address(regT0), ImmPtr(globalData->jsStringVPtr))); + failures.append(jit.branchPtr(NotEqual, Address(regT0), TrustedImmPtr(globalData->jsStringVPtr))); failures.append(jit.branchTest32(NonZero, Address(regT0, OBJECT_OFFSETOF(JSString, m_fiberCount)))); // Load string length to regT1, and start the process of loading the data pointer into regT0 @@ -285,14 +285,14 @@ JIT::CodePtr JIT::stringGetByValStubGenerator(JSGlobalData* globalData, Executab // Load the character jit.load16(BaseIndex(regT0, regT2, TimesTwo, 0), regT0); - failures.append(jit.branch32(AboveOrEqual, regT0, Imm32(0x100))); - jit.move(ImmPtr(globalData->smallStrings.singleCharacterStrings()), regT1); + failures.append(jit.branch32(AboveOrEqual, regT0, TrustedImm32(0x100))); + jit.move(TrustedImmPtr(globalData->smallStrings.singleCharacterStrings()), regT1); jit.loadPtr(BaseIndex(regT1, regT0, ScalePtr, 0), regT0); - jit.move(Imm32(JSValue::CellTag), regT1); // We null check regT0 on return so this is safe + jit.move(TrustedImm32(JSValue::CellTag), regT1); // We null check regT0 on return so this is safe jit.ret(); failures.link(&jit); - jit.move(Imm32(0), regT0); + jit.move(TrustedImm32(0), regT0); jit.ret(); LinkBuffer patchBuffer(&jit, pool, 0); @@ -307,16 +307,16 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction) emitLoad2(base, regT1, regT0, property, regT3, regT2); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); emitJumpSlowCaseIfNotJSCell(base, regT1); - addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr))); + addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr))); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT3); - addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, OBJECT_OFFSETOF(JSArray, m_vectorLength)))); + loadPtr(Address(regT0, JSArray::storageOffset()), regT3); + addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset()))); load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload - addSlowCase(branch32(Equal, regT1, Imm32(JSValue::EmptyValueTag))); + addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag))); emitStore(dst, regT1, regT0); map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_val), dst, regT1, regT0); @@ -333,7 +333,7 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas Jump nonCell = jump(); linkSlowCase(iter); // base array check - Jump notString = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)); + Jump notString = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)); emitNakedCall(m_globalData->getCTIStub(stringGetByValStubGenerator)); Jump failed = branchTestPtr(Zero, regT0); emitStore(dst, regT1, regT0); @@ -359,14 +359,14 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction) emitLoad2(base, regT1, regT0, property, regT3, regT2); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); emitJumpSlowCaseIfNotJSCell(base, regT1); - addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr))); - addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, OBJECT_OFFSETOF(JSArray, m_vectorLength)))); + addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr))); + addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset()))); - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT3); + loadPtr(Address(regT0, JSArray::storageOffset()), regT3); - Jump empty = branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), Imm32(JSValue::EmptyValueTag)); + Jump empty = branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)); Label storeResult(this); emitLoad(value, regT1, regT0); @@ -375,10 +375,10 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction) Jump end = jump(); empty.link(this); - add32(Imm32(1), Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); + add32(TrustedImm32(1), Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); branch32(Below, regT2, Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_length))).linkTo(storeResult, this); - add32(Imm32(1), regT2, regT0); + add32(TrustedImm32(1), regT2, regT0); store32(regT0, Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_length))); jump().linkTo(storeResult, this); @@ -429,7 +429,7 @@ void JIT::compileGetByIdHotPath() m_propertyAccessInstructionIndex++; DataLabelPtr structureToCompare; - Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); + Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); addSlowCase(structureCheck); ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetGetByIdStructure); ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureCheck), patchOffsetGetByIdBranchToSlowCase); @@ -472,7 +472,7 @@ void JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<Sl #endif JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id); stubCall.addArgument(regT1, regT0); - stubCall.addArgument(ImmPtr(ident)); + stubCall.addArgument(TrustedImmPtr(ident)); Call call = stubCall.call(dst); END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase); @@ -505,7 +505,7 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction) // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over. DataLabelPtr structureToCompare; - addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)))); + addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)))); ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT0); @@ -529,7 +529,7 @@ void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCase JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct : cti_op_put_by_id); stubCall.addArgument(regT1, regT0); - stubCall.addArgument(ImmPtr(&(m_codeBlock->identifier(ident)))); + stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident)))); stubCall.addArgument(regT3, regT2); Call call = stubCall.call(); @@ -579,10 +579,10 @@ void JIT::testPrototype(JSValue prototype, JumpList& failureCases) // values. In the non X86_64 case, the generated code is slightly more efficient because it uses // two less instructions and doesn't require any scratch registers. #if CPU(X86_64) - move(ImmPtr(prototype.asCell()->structure()), regT3); - failureCases.append(branchPtr(NotEqual, AbsoluteAddress(&prototype.asCell()->m_structure), regT3)); + move(TrustedImmPtr(prototype.asCell()->structure()), regT3); + failureCases.append(branchPtr(NotEqual, AbsoluteAddress(prototype.asCell()->addressOfStructure()), regT3)); #else - failureCases.append(branchPtr(NotEqual, AbsoluteAddress(&prototype.asCell()->m_structure), ImmPtr(prototype.asCell()->structure()))); + failureCases.append(branchPtr(NotEqual, AbsoluteAddress(prototype.asCell()->addressOfStructure()), TrustedImmPtr(prototype.asCell()->structure()))); #endif } @@ -591,8 +591,8 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure // It is assumed that regT0 contains the basePayload and regT1 contains the baseTag. The value can be found on the stack. JumpList failureCases; - failureCases.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); - failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure))); + failureCases.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag))); + failureCases.append(branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(oldStructure))); testPrototype(oldStructure->storedPrototype(), failureCases); if (!direct) { @@ -613,16 +613,16 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure stubCall.skipArgument(); // base stubCall.skipArgument(); // ident stubCall.skipArgument(); // value - stubCall.addArgument(Imm32(oldStructure->propertyStorageCapacity())); - stubCall.addArgument(Imm32(newStructure->propertyStorageCapacity())); + stubCall.addArgument(TrustedImm32(oldStructure->propertyStorageCapacity())); + stubCall.addArgument(TrustedImm32(newStructure->propertyStorageCapacity())); stubCall.call(regT0); restoreReturnAddressBeforeReturn(regT3); } - sub32(Imm32(1), AbsoluteAddress(oldStructure->addressOfCount())); - add32(Imm32(1), AbsoluteAddress(newStructure->addressOfCount())); - storePtr(ImmPtr(newStructure), Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure))); + sub32(TrustedImm32(1), AbsoluteAddress(oldStructure->addressOfCount())); + add32(TrustedImm32(1), AbsoluteAddress(newStructure->addressOfCount())); + storePtr(TrustedImmPtr(newStructure), Address(regT0, JSCell::structureOffset())); #if CPU(MIPS) // For MIPS, we don't add sizeof(void*) to the stack offset. @@ -717,15 +717,15 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress) // regT0 holds a JSCell* // Check for array - Jump failureCases1 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)); + Jump failureCases1 = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)); // Checks out okay! - get the length from the storage - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2); + loadPtr(Address(regT0, JSArray::storageOffset()), regT2); load32(Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length)), regT2); - Jump failureCases2 = branch32(Above, regT2, Imm32(INT_MAX)); + Jump failureCases2 = branch32(Above, regT2, TrustedImm32(INT_MAX)); move(regT2, regT0); - move(Imm32(JSValue::Int32Tag), regT1); + move(TrustedImm32(JSValue::Int32Tag), regT1); Jump success = jump(); LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0); @@ -762,12 +762,12 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str Jump failureCases1 = checkStructure(regT0, structure); // Check the prototype object's Structure had not changed. - Structure** prototypeStructureAddress = &(protoObject->m_structure); + Structure* const * prototypeStructureAddress = protoObject->addressOfStructure(); #if CPU(X86_64) - move(ImmPtr(prototypeStructure), regT3); + move(TrustedImmPtr(prototypeStructure), regT3); Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3); #else - Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure)); + Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), TrustedImmPtr(prototypeStructure)); #endif bool needsStubLink = false; // Checks out okay! @@ -777,15 +777,15 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); stubCall.addArgument(regT1); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else if (slot.cachedPropertyType() == PropertySlot::Custom) { needsStubLink = true; JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); - stubCall.addArgument(ImmPtr(protoObject)); - stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); - stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(protoObject)); + stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); @@ -834,15 +834,15 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); stubCall.addArgument(regT1); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else if (slot.cachedPropertyType() == PropertySlot::Custom) { needsStubLink = true; JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); - stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else compileGetDirectOffset(regT0, regT1, regT0, structure, cachedOffset); @@ -889,12 +889,12 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi Jump failureCases1 = checkStructure(regT0, structure); // Check the prototype object's Structure had not changed. - Structure** prototypeStructureAddress = &(protoObject->m_structure); + Structure* const * prototypeStructureAddress = protoObject->addressOfStructure(); #if CPU(X86_64) - move(ImmPtr(prototypeStructure), regT3); + move(TrustedImmPtr(prototypeStructure), regT3); Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3); #else - Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure)); + Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), TrustedImmPtr(prototypeStructure)); #endif bool needsStubLink = false; @@ -904,15 +904,15 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); stubCall.addArgument(regT1); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else if (slot.cachedPropertyType() == PropertySlot::Custom) { needsStubLink = true; JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); - stubCall.addArgument(ImmPtr(protoObject)); - stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); - stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(protoObject)); + stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); @@ -973,15 +973,15 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); stubCall.addArgument(regT1); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else if (slot.cachedPropertyType() == PropertySlot::Custom) { needsStubLink = true; JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); - stubCall.addArgument(ImmPtr(protoObject)); - stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); - stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(protoObject)); + stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); @@ -1007,8 +1007,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi // Track the stub we have created so that it will be deleted later. structure->ref(); - chain->ref(); - prototypeStructures->list[currentIndex].set(entryLabel, structure, chain); + prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), entryLabel, structure, chain); // Finally patch the jump to slow case back in the hot path to jump here instead. CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); @@ -1043,15 +1042,15 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); stubCall.addArgument(regT1); stubCall.addArgument(regT0); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else if (slot.cachedPropertyType() == PropertySlot::Custom) { needsStubLink = true; JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); - stubCall.addArgument(ImmPtr(protoObject)); - stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); - stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); - stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.addArgument(TrustedImmPtr(protoObject)); + stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress())); stubCall.call(); } else compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); @@ -1113,10 +1112,10 @@ void JIT::emit_op_get_by_pname(Instruction* currentInstruction) emitLoadPayload(iter, regT1); // Test base's structure - loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT0); + loadPtr(Address(regT2, JSCell::structureOffset()), regT0); addSlowCase(branchPtr(NotEqual, regT0, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure)))); load32(addressFor(i), regT3); - sub32(Imm32(1), regT3); + sub32(TrustedImm32(1), regT3); addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots)))); compileGetDirectOffset(regT2, regT1, regT0, regT3); diff --git a/Source/JavaScriptCore/jit/JITStubCall.h b/Source/JavaScriptCore/jit/JITStubCall.h index 4478d06..a0341d6 100644 --- a/Source/JavaScriptCore/jit/JITStubCall.h +++ b/Source/JavaScriptCore/jit/JITStubCall.h @@ -99,13 +99,13 @@ namespace JSC { m_stackIndex += stackIndexStep; } - void addArgument(JIT::Imm32 argument) + void addArgument(JIT::TrustedImm32 argument) { m_jit->poke(argument, m_stackIndex); m_stackIndex += stackIndexStep; } - void addArgument(JIT::ImmPtr argument) + void addArgument(JIT::TrustedImmPtr argument) { m_jit->poke(argument, m_stackIndex); m_stackIndex += stackIndexStep; diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp index 95bf52c..e52c7c8 100644 --- a/Source/JavaScriptCore/jit/JITStubs.cpp +++ b/Source/JavaScriptCore/jit/JITStubs.cpp @@ -40,6 +40,7 @@ #include "Debugger.h" #include "ExceptionHelpers.h" #include "GetterSetter.h" +#include "Global.h" #include "JIT.h" #include "JSActivation.h" #include "JSArray.h" @@ -679,6 +680,7 @@ __asm void ctiOpThrowNotCaught() #endif JITThunks::JITThunks(JSGlobalData* globalData) + : m_hostFunctionStubMap(new HostFunctionStubMap) { if (!globalData->executableAllocator.isValid()) return; @@ -941,17 +943,17 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD #define CHECK_FOR_EXCEPTION() \ do { \ - if (UNLIKELY(stackFrame.globalData->exception.get())) \ + if (UNLIKELY(stackFrame.globalData->exception)) \ VM_THROW_EXCEPTION(); \ } while (0) #define CHECK_FOR_EXCEPTION_AT_END() \ do { \ - if (UNLIKELY(stackFrame.globalData->exception.get())) \ + if (UNLIKELY(stackFrame.globalData->exception)) \ VM_THROW_EXCEPTION_AT_END(); \ } while (0) #define CHECK_FOR_EXCEPTION_VOID() \ do { \ - if (UNLIKELY(stackFrame.globalData->exception.get())) { \ + if (UNLIKELY(stackFrame.globalData->exception)) { \ VM_THROW_EXCEPTION_AT_END(); \ return; \ } \ @@ -976,7 +978,7 @@ static ExceptionHandler jitThrow(JSGlobalData* globalData, CallFrame* callFrame, return exceptionHandler; } -#if CPU(ARM_THUMB2) +#if CPU(ARM_THUMB2) && COMPILER(GCC) #define DEFINE_STUB_FUNCTION(rtype, op) \ extern "C" { \ @@ -1072,7 +1074,7 @@ static ExceptionHandler jitThrow(JSGlobalData* globalData, CallFrame* callFrame, ); \ rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) -#elif CPU(ARM_TRADITIONAL) && COMPILER(RVCT) +#elif (CPU(ARM_THUMB2) || CPU(ARM_TRADITIONAL)) && COMPILER(RVCT) #define DEFINE_STUB_FUNCTION(rtype, op) rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) @@ -1085,7 +1087,7 @@ static ExceptionHandler jitThrow(JSGlobalData* globalData, CallFrame* callFrame, RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);) RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION)) RVCT({) -RVCT( ARM) +RVCT( PRESERVE8) RVCT( IMPORT JITStubThunked_#op#) RVCT( str lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET]) RVCT( bl JITStubThunked_#op#) @@ -1172,7 +1174,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_this) Structure* structure; JSValue proto = stackFrame.args[0].jsValue(); if (proto.isObject()) - structure = asObject(proto)->inheritorID(); + structure = asObject(proto)->inheritorID(*stackFrame.globalData); else structure = constructor->scope()->globalObject->emptyObjectStructure(); JSValue result = constructEmptyObject(callFrame, structure); @@ -1551,7 +1553,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail) return JSValue::encode(result); } -static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(StructureStubInfo* stubInfo, int& listIndex) +static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(JSGlobalData& globalData, ScriptExecutable* owner, StructureStubInfo* stubInfo, int& listIndex) { PolymorphicAccessStructureList* prototypeStructureList = 0; listIndex = 1; @@ -1563,7 +1565,7 @@ static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(Str stubInfo->initGetByIdProtoList(prototypeStructureList, 2); break; case access_get_by_id_chain: - prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain); + prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain); stubInfo->stubRoutine = CodeLocationLabel(); stubInfo->initGetByIdProtoList(prototypeStructureList, 2); break; @@ -1651,7 +1653,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list) } int listIndex; - PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex); + PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->globalData(), codeBlock->ownerExecutable(), stubInfo, listIndex); if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) { JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), propertyName, slot, offset); @@ -1661,7 +1663,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list) } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) { ASSERT(!baseValue.asCell()->structure()->isDictionary()); int listIndex; - PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex); + PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->globalData(), codeBlock->ownerExecutable(), stubInfo, listIndex); if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) { StructureChain* protoChain = structure->prototypeChain(callFrame); @@ -3067,7 +3069,15 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_regexp) { STUB_INIT_STACK_FRAME(stackFrame); - return new (stackFrame.globalData) RegExpObject(stackFrame.callFrame->lexicalGlobalObject(), stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), stackFrame.args[0].regExp()); + CallFrame* callFrame = stackFrame.callFrame; + + RegExp* regExp = stackFrame.args[0].regExp(); + if (!regExp->isValid()) { + stackFrame.globalData->exception = createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor."); + VM_THROW_EXCEPTION(); + } + + return new (stackFrame.globalData) RegExpObject(stackFrame.callFrame->lexicalGlobalObject(), stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), regExp); } DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor) @@ -3462,7 +3472,7 @@ DEFINE_STUB_FUNCTION(void*, vm_throw) { STUB_INIT_STACK_FRAME(stackFrame); JSGlobalData* globalData = stackFrame.globalData; - ExceptionHandler handler = jitThrow(globalData, stackFrame.callFrame, globalData->exception.get(), globalData->exceptionLocation); + ExceptionHandler handler = jitThrow(globalData, stackFrame.callFrame, globalData->exception, globalData->exceptionLocation); STUB_SET_RETURN_ADDRESS(handler.catchRoutine); return handler.callFrame; } @@ -3483,22 +3493,27 @@ MacroAssemblerCodePtr JITThunks::ctiStub(JSGlobalData* globalData, ThunkGenerato return entry.first->second; } -PassRefPtr<NativeExecutable> JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function) +NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function) { - std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap.add(function, 0); + std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap->add(function, Global<NativeExecutable>(Global<NativeExecutable>::EmptyValue)); if (entry.second) - entry.first->second = NativeExecutable::create(JIT::compileCTINativeCall(globalData, m_executablePool, function), function, ctiNativeConstruct(), callHostFunctionAsConstructor); - return entry.first->second; + entry.first->second.set(*globalData, NativeExecutable::create(*globalData, JIT::compileCTINativeCall(globalData, m_executablePool, function), function, ctiNativeConstruct(), callHostFunctionAsConstructor)); + return entry.first->second.get(); } -PassRefPtr<NativeExecutable> JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, ThunkGenerator generator) +NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, ThunkGenerator generator) { - std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap.add(function, 0); + std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap->add(function, Global<NativeExecutable>(Global<NativeExecutable>::EmptyValue)); if (entry.second) { MacroAssemblerCodePtr code = globalData->canUseJIT() ? generator(globalData, m_executablePool.get()) : MacroAssemblerCodePtr(); - entry.first->second = NativeExecutable::create(code, function, ctiNativeConstruct(), callHostFunctionAsConstructor); + entry.first->second.set(*globalData, NativeExecutable::create(*globalData, code, function, ctiNativeConstruct(), callHostFunctionAsConstructor)); } - return entry.first->second; + return entry.first->second.get(); +} + +void JITThunks::clearHostFunctionStubs() +{ + m_hostFunctionStubMap.clear(); } } // namespace JSC diff --git a/Source/JavaScriptCore/jit/JITStubs.h b/Source/JavaScriptCore/jit/JITStubs.h index 65f6a55..af6e13f 100644 --- a/Source/JavaScriptCore/jit/JITStubs.h +++ b/Source/JavaScriptCore/jit/JITStubs.h @@ -254,6 +254,8 @@ namespace JSC { extern "C" void ctiOpThrowNotCaught(); extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*); + template <typename T> class Global; + class JITThunks { public: JITThunks(JSGlobalData*); @@ -273,13 +275,16 @@ namespace JSC { MacroAssemblerCodePtr ctiStub(JSGlobalData* globalData, ThunkGenerator generator); - PassRefPtr<NativeExecutable> hostFunctionStub(JSGlobalData* globalData, NativeFunction func); - PassRefPtr<NativeExecutable> hostFunctionStub(JSGlobalData* globalData, NativeFunction func, ThunkGenerator generator); + NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction); + NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction, ThunkGenerator); + + void clearHostFunctionStubs(); + private: typedef HashMap<ThunkGenerator, MacroAssemblerCodePtr> CTIStubMap; CTIStubMap m_ctiStubMap; - typedef HashMap<NativeFunction, RefPtr<NativeExecutable> > HostFunctionStubMap; - HostFunctionStubMap m_hostFunctionStubMap; + typedef HashMap<NativeFunction, Global<NativeExecutable> > HostFunctionStubMap; + OwnPtr<HostFunctionStubMap> m_hostFunctionStubMap; RefPtr<ExecutablePool> m_executablePool; TrampolineStructure m_trampolineStructure; diff --git a/Source/JavaScriptCore/jit/JSInterfaceJIT.h b/Source/JavaScriptCore/jit/JSInterfaceJIT.h index 6453bab..5d3f239 100644 --- a/Source/JavaScriptCore/jit/JSInterfaceJIT.h +++ b/Source/JavaScriptCore/jit/JSInterfaceJIT.h @@ -29,6 +29,7 @@ #include "JITCode.h" #include "JITStubs.h" #include "JSImmediate.h" +#include "JSValue.h" #include "MacroAssembler.h" #include "RegisterFile.h" #include <wtf/AlwaysInline.h> @@ -157,13 +158,20 @@ namespace JSC { #error "JIT not supported on this platform." #endif +#if USE(JSVALUE32_64) + // Can't just propogate JSValue::Int32Tag as visual studio doesn't like it + static const unsigned Int32Tag = 0xfffffffd; + COMPILE_ASSERT(Int32Tag == JSValue::Int32Tag, Int32Tag_out_of_sync); +#else + static const unsigned Int32Tag = JSImmediate::TagTypeNumber >> 32; +#endif inline Jump emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID payload); inline Jump emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst); inline Jump emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch); #if USE(JSVALUE32_64) inline Jump emitJumpIfNotJSCell(unsigned virtualRegisterIndex); - inline Address tagFor(unsigned index, RegisterID base = callFrameRegister); + inline Address tagFor(int index, RegisterID base = callFrameRegister); #endif #if USE(JSVALUE64) @@ -172,8 +180,10 @@ namespace JSC { void emitFastArithImmToInt(RegisterID reg); #endif - inline Address payloadFor(unsigned index, RegisterID base = callFrameRegister); - inline Address addressFor(unsigned index, RegisterID base = callFrameRegister); + inline Address payloadFor(int index, RegisterID base = callFrameRegister); + inline Address intPayloadFor(int index, RegisterID base = callFrameRegister); + inline Address intTagFor(int index, RegisterID base = callFrameRegister); + inline Address addressFor(int index, RegisterID base = callFrameRegister); }; struct ThunkHelpers { @@ -192,34 +202,44 @@ namespace JSC { inline JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotJSCell(unsigned virtualRegisterIndex) { ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex); - return branch32(NotEqual, tagFor(virtualRegisterIndex), Imm32(JSValue::CellTag)); + return branch32(NotEqual, tagFor(virtualRegisterIndex), TrustedImm32(JSValue::CellTag)); } inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst) { ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex); loadPtr(payloadFor(virtualRegisterIndex), dst); - return branch32(NotEqual, tagFor(virtualRegisterIndex), Imm32(JSValue::Int32Tag)); + return branch32(NotEqual, tagFor(static_cast<int>(virtualRegisterIndex)), TrustedImm32(JSValue::Int32Tag)); } - inline JSInterfaceJIT::Address JSInterfaceJIT::tagFor(unsigned virtualRegisterIndex, RegisterID base) + inline JSInterfaceJIT::Address JSInterfaceJIT::tagFor(int virtualRegisterIndex, RegisterID base) { - ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex); - return Address(base, (virtualRegisterIndex * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); + ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex); + return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); } - inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(unsigned virtualRegisterIndex, RegisterID base) + inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(int virtualRegisterIndex, RegisterID base) { - ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex); - return Address(base, (virtualRegisterIndex * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); + ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex); + return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); + } + + inline JSInterfaceJIT::Address JSInterfaceJIT::intPayloadFor(int virtualRegisterIndex, RegisterID base) + { + return payloadFor(virtualRegisterIndex, base); + } + + inline JSInterfaceJIT::Address JSInterfaceJIT::intTagFor(int virtualRegisterIndex, RegisterID base) + { + return tagFor(virtualRegisterIndex, base); } inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch) { ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex); loadPtr(tagFor(virtualRegisterIndex), scratch); - Jump isDouble = branch32(Below, scratch, Imm32(JSValue::LowestTag)); - Jump notInt = branch32(NotEqual, scratch, Imm32(JSValue::Int32Tag)); + Jump isDouble = branch32(Below, scratch, TrustedImm32(JSValue::LowestTag)); + Jump notInt = branch32(NotEqual, scratch, TrustedImm32(JSValue::Int32Tag)); loadPtr(payloadFor(virtualRegisterIndex), scratch); convertInt32ToDouble(scratch, dst); Jump done = jump(); @@ -274,17 +294,28 @@ namespace JSC { #endif #if USE(JSVALUE64) - inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(unsigned virtualRegisterIndex, RegisterID base) + inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(int virtualRegisterIndex, RegisterID base) { - ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex); + ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex); return addressFor(virtualRegisterIndex, base); } + + inline JSInterfaceJIT::Address JSInterfaceJIT::intPayloadFor(int virtualRegisterIndex, RegisterID base) + { + ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex); + return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)); + } + inline JSInterfaceJIT::Address JSInterfaceJIT::intTagFor(int virtualRegisterIndex, RegisterID base) + { + ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex); + return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); + } #endif - inline JSInterfaceJIT::Address JSInterfaceJIT::addressFor(unsigned virtualRegisterIndex, RegisterID base) + inline JSInterfaceJIT::Address JSInterfaceJIT::addressFor(int virtualRegisterIndex, RegisterID base) { - ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex); - return Address(base, (virtualRegisterIndex * sizeof(Register))); + ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex); + return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register))); } } diff --git a/Source/JavaScriptCore/jit/SpecializedThunkJIT.h b/Source/JavaScriptCore/jit/SpecializedThunkJIT.h index 5c593d9..8c79692 100644 --- a/Source/JavaScriptCore/jit/SpecializedThunkJIT.h +++ b/Source/JavaScriptCore/jit/SpecializedThunkJIT.h @@ -43,7 +43,7 @@ namespace JSC { , m_pool(pool) { // Check that we have the expected number of arguments - m_failures.append(branch32(NotEqual, Address(callFrameRegister, RegisterFile::ArgumentCount * (int)sizeof(Register)), Imm32(expectedArgCount + 1))); + m_failures.append(branch32(NotEqual, Address(callFrameRegister, RegisterFile::ArgumentCount * (int)sizeof(Register)), TrustedImm32(expectedArgCount + 1))); } void loadDoubleArgument(int argument, FPRegisterID dst, RegisterID scratch) @@ -61,7 +61,7 @@ namespace JSC { void loadJSStringArgument(int argument, RegisterID dst) { loadCellArgument(argument, dst); - m_failures.append(branchPtr(NotEqual, Address(dst, 0), ImmPtr(m_globalData->jsStringVPtr))); + m_failures.append(branchPtr(NotEqual, Address(dst, 0), TrustedImmPtr(m_globalData->jsStringVPtr))); m_failures.append(branchTest32(NonZero, Address(dst, OBJECT_OFFSETOF(JSString, m_fiberCount)))); } @@ -87,7 +87,7 @@ namespace JSC { { if (src != regT0) move(src, regT0); - loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister); + loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister); ret(); } @@ -101,7 +101,7 @@ namespace JSC { loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.tag) - sizeof(double)), regT1); loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.payload) - sizeof(double)), regT0); #endif - loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister); + loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister); ret(); } @@ -110,7 +110,7 @@ namespace JSC { if (src != regT0) move(src, regT0); tagReturnAsInt32(); - loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister); + loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister); ret(); } @@ -119,7 +119,7 @@ namespace JSC { if (src != regT0) move(src, regT0); tagReturnAsJSCell(); - loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister); + loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister); ret(); } @@ -141,14 +141,14 @@ namespace JSC { #if USE(JSVALUE64) orPtr(tagTypeNumberRegister, regT0); #else - move(Imm32(JSValue::Int32Tag), regT1); + move(TrustedImm32(JSValue::Int32Tag), regT1); #endif } void tagReturnAsJSCell() { #if USE(JSVALUE32_64) - move(Imm32(JSValue::CellTag), regT1); + move(TrustedImm32(JSValue::CellTag), regT1); #endif } diff --git a/Source/JavaScriptCore/jit/ThunkGenerators.cpp b/Source/JavaScriptCore/jit/ThunkGenerators.cpp index 9b40f12..1201696 100644 --- a/Source/JavaScriptCore/jit/ThunkGenerators.cpp +++ b/Source/JavaScriptCore/jit/ThunkGenerators.cpp @@ -57,8 +57,8 @@ static void stringCharLoad(SpecializedThunkJIT& jit) static void charToString(SpecializedThunkJIT& jit, JSGlobalData* globalData, MacroAssembler::RegisterID src, MacroAssembler::RegisterID dst, MacroAssembler::RegisterID scratch) { - jit.appendFailure(jit.branch32(MacroAssembler::AboveOrEqual, src, MacroAssembler::Imm32(0x100))); - jit.move(MacroAssembler::ImmPtr(globalData->smallStrings.singleCharacterStrings()), scratch); + jit.appendFailure(jit.branch32(MacroAssembler::AboveOrEqual, src, MacroAssembler::TrustedImm32(0x100))); + jit.move(MacroAssembler::TrustedImmPtr(globalData->smallStrings.singleCharacterStrings()), scratch); jit.loadPtr(MacroAssembler::BaseIndex(scratch, src, MacroAssembler::ScalePtr, 0), dst); jit.appendFailure(jit.branchTestPtr(MacroAssembler::Zero, dst)); } @@ -115,16 +115,16 @@ MacroAssemblerCodePtr powThunkGenerator(JSGlobalData* globalData, ExecutablePool jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0); MacroAssembler::Jump nonIntExponent; jit.loadInt32Argument(1, SpecializedThunkJIT::regT0, nonIntExponent); - jit.appendFailure(jit.branch32(MacroAssembler::LessThan, SpecializedThunkJIT::regT0, MacroAssembler::Imm32(0))); + jit.appendFailure(jit.branch32(MacroAssembler::LessThan, SpecializedThunkJIT::regT0, MacroAssembler::TrustedImm32(0))); MacroAssembler::Jump exponentIsZero = jit.branchTest32(MacroAssembler::Zero, SpecializedThunkJIT::regT0); MacroAssembler::Label startLoop(jit.label()); - MacroAssembler::Jump exponentIsEven = jit.branchTest32(MacroAssembler::Zero, SpecializedThunkJIT::regT0, MacroAssembler::Imm32(1)); + MacroAssembler::Jump exponentIsEven = jit.branchTest32(MacroAssembler::Zero, SpecializedThunkJIT::regT0, MacroAssembler::TrustedImm32(1)); jit.mulDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1); exponentIsEven.link(&jit); jit.mulDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0); - jit.rshift32(MacroAssembler::Imm32(1), SpecializedThunkJIT::regT0); + jit.rshift32(MacroAssembler::TrustedImm32(1), SpecializedThunkJIT::regT0); jit.branchTest32(MacroAssembler::NonZero, SpecializedThunkJIT::regT0).linkTo(startLoop, &jit); exponentIsZero.link(&jit); diff --git a/Source/JavaScriptCore/jsc.cpp b/Source/JavaScriptCore/jsc.cpp index 1873659..8ccb039 100644 --- a/Source/JavaScriptCore/jsc.cpp +++ b/Source/JavaScriptCore/jsc.cpp @@ -141,14 +141,14 @@ long StopWatch::getElapsedMS() class GlobalObject : public JSGlobalObject { public: - GlobalObject(const Vector<UString>& arguments); + GlobalObject(JSGlobalData&, const Vector<UString>& arguments); virtual UString className() const { return "global"; } }; COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false); ASSERT_CLASS_FITS_IN_CELL(GlobalObject); -GlobalObject::GlobalObject(const Vector<UString>& arguments) - : JSGlobalObject() +GlobalObject::GlobalObject(JSGlobalData& globalData, const Vector<UString>& arguments) + : JSGlobalObject(globalData) { putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "debug"), functionDebug)); putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "print"), functionPrint)); @@ -212,7 +212,7 @@ EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec) if (!fillBufferWithContentsOfFile(fileName, script)) return JSValue::encode(throwError(exec, createError(exec, "Could not open file."))); - GlobalObject* globalObject = new (&exec->globalData()) GlobalObject(Vector<UString>()); + GlobalObject* globalObject = new (&exec->globalData()) GlobalObject(exec->globalData(), Vector<UString>()); StopWatch stopWatch; stopWatch.start(); @@ -536,7 +536,7 @@ int jscmain(int argc, char** argv, JSGlobalData* globalData) Options options; parseArguments(argc, argv, options, globalData); - GlobalObject* globalObject = new (globalData) GlobalObject(options.arguments); + GlobalObject* globalObject = new (globalData) GlobalObject(*globalData, options.arguments); bool success = runWithScripts(globalObject, options.scripts, options.dump); if (options.interactive && success) runInteractive(globalObject); diff --git a/Source/JavaScriptCore/jsc.pro b/Source/JavaScriptCore/jsc.pro index a550c48..21ffeea 100644 --- a/Source/JavaScriptCore/jsc.pro +++ b/Source/JavaScriptCore/jsc.pro @@ -27,6 +27,10 @@ mac { LIBS_PRIVATE += -framework AppKit } +win* { + LIBS += -ladvapi32 +} + wince* { LIBS += mmtimer.lib } diff --git a/Source/JavaScriptCore/profiler/CallIdentifier.h b/Source/JavaScriptCore/profiler/CallIdentifier.h index a9827c0..1ba5ec6 100644 --- a/Source/JavaScriptCore/profiler/CallIdentifier.h +++ b/Source/JavaScriptCore/profiler/CallIdentifier.h @@ -63,7 +63,7 @@ namespace JSC { key.m_url.impl()->hash(), key.m_lineNumber }; - return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes); + return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes); } static bool equal(const CallIdentifier& a, const CallIdentifier& b) { return a == b; } diff --git a/Source/JavaScriptCore/profiler/ProfileGenerator.cpp b/Source/JavaScriptCore/profiler/ProfileGenerator.cpp index 68d1733..5db38bc 100644 --- a/Source/JavaScriptCore/profiler/ProfileGenerator.cpp +++ b/Source/JavaScriptCore/profiler/ProfileGenerator.cpp @@ -40,19 +40,19 @@ namespace JSC { static const char* NonJSExecution = "(idle)"; -PassRefPtr<ProfileGenerator> ProfileGenerator::create(const UString& title, ExecState* originatingExec, unsigned uid) +PassRefPtr<ProfileGenerator> ProfileGenerator::create(ExecState* exec, const UString& title, unsigned uid) { - return adoptRef(new ProfileGenerator(title, originatingExec, uid)); + return adoptRef(new ProfileGenerator(exec, title, uid)); } -ProfileGenerator::ProfileGenerator(const UString& title, ExecState* originatingExec, unsigned uid) - : m_originatingGlobalExec(originatingExec ? originatingExec->lexicalGlobalObject()->globalExec() : 0) - , m_profileGroup(originatingExec ? originatingExec->lexicalGlobalObject()->profileGroup() : 0) +ProfileGenerator::ProfileGenerator(ExecState* exec, const UString& title, unsigned uid) + : m_origin(exec ? exec->lexicalGlobalObject() : 0) + , m_profileGroup(exec ? exec->lexicalGlobalObject()->profileGroup() : 0) { m_profile = Profile::create(title, uid); m_currentNode = m_head = m_profile->head(); - if (originatingExec) - addParentForConsoleStart(originatingExec); + if (exec) + addParentForConsoleStart(exec); } void ProfileGenerator::addParentForConsoleStart(ExecState* exec) @@ -80,7 +80,7 @@ void ProfileGenerator::willExecute(ExecState* callerCallFrame, const CallIdentif JAVASCRIPTCORE_PROFILE_WILL_EXECUTE(m_profileGroup, const_cast<char*>(name.data()), const_cast<char*>(url.data()), callIdentifier.m_lineNumber); } - if (!m_originatingGlobalExec) + if (!m_origin) return; ASSERT(m_currentNode); @@ -95,7 +95,7 @@ void ProfileGenerator::didExecute(ExecState* callerCallFrame, const CallIdentifi JAVASCRIPTCORE_PROFILE_DID_EXECUTE(m_profileGroup, const_cast<char*>(name.data()), const_cast<char*>(url.data()), callIdentifier.m_lineNumber); } - if (!m_originatingGlobalExec) + if (!m_origin) return; ASSERT(m_currentNode); diff --git a/Source/JavaScriptCore/profiler/ProfileGenerator.h b/Source/JavaScriptCore/profiler/ProfileGenerator.h index cbed73b..8c8b817 100644 --- a/Source/JavaScriptCore/profiler/ProfileGenerator.h +++ b/Source/JavaScriptCore/profiler/ProfileGenerator.h @@ -34,6 +34,7 @@ namespace JSC { class ExecState; + class JSGlobalObject; class Profile; class ProfileNode; class UString; @@ -41,12 +42,12 @@ namespace JSC { class ProfileGenerator : public RefCounted<ProfileGenerator> { public: - static PassRefPtr<ProfileGenerator> create(const UString& title, ExecState* originatingExec, unsigned uid); + static PassRefPtr<ProfileGenerator> create(ExecState*, const UString& title, unsigned uid); // Members const UString& title() const; PassRefPtr<Profile> profile() const { return m_profile; } - ExecState* originatingGlobalExec() const { return m_originatingGlobalExec; } + JSGlobalObject* origin() const { return m_origin; } unsigned profileGroup() const { return m_profileGroup; } // Collecting @@ -61,14 +62,14 @@ namespace JSC { typedef void (ProfileGenerator::*ProfileFunction)(ExecState* callerOrHandlerCallFrame, const CallIdentifier& callIdentifier); private: - ProfileGenerator(const UString& title, ExecState* originatingExec, unsigned uid); + ProfileGenerator(ExecState*, const UString& title, unsigned uid); void addParentForConsoleStart(ExecState*); void removeProfileStart(); void removeProfileEnd(); RefPtr<Profile> m_profile; - ExecState* m_originatingGlobalExec; + JSGlobalObject* m_origin; unsigned m_profileGroup; RefPtr<ProfileNode> m_head; RefPtr<ProfileNode> m_currentNode; diff --git a/Source/JavaScriptCore/profiler/Profiler.cpp b/Source/JavaScriptCore/profiler/Profiler.cpp index 301dc0c..bcaaaac 100644 --- a/Source/JavaScriptCore/profiler/Profiler.cpp +++ b/Source/JavaScriptCore/profiler/Profiler.cpp @@ -66,25 +66,25 @@ void Profiler::startProfiling(ExecState* exec, const UString& title) // Check if we currently have a Profile for this global ExecState and title. // If so return early and don't create a new Profile. - ExecState* globalExec = exec ? exec->lexicalGlobalObject()->globalExec() : 0; + JSGlobalObject* origin = exec ? exec->lexicalGlobalObject() : 0; for (size_t i = 0; i < m_currentProfiles.size(); ++i) { ProfileGenerator* profileGenerator = m_currentProfiles[i].get(); - if (profileGenerator->originatingGlobalExec() == globalExec && profileGenerator->title() == title) + if (profileGenerator->origin() == origin && profileGenerator->title() == title) return; } s_sharedEnabledProfilerReference = this; - RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(title, exec, ++ProfilesUID); + RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(exec, title, ++ProfilesUID); m_currentProfiles.append(profileGenerator); } PassRefPtr<Profile> Profiler::stopProfiling(ExecState* exec, const UString& title) { - ExecState* globalExec = exec ? exec->lexicalGlobalObject()->globalExec() : 0; + JSGlobalObject* origin = exec ? exec->lexicalGlobalObject() : 0; for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) { ProfileGenerator* profileGenerator = m_currentProfiles[i].get(); - if (profileGenerator->originatingGlobalExec() == globalExec && (title.isNull() || profileGenerator->title() == title)) { + if (profileGenerator->origin() == origin && (title.isNull() || profileGenerator->title() == title)) { profileGenerator->stopProfiling(); RefPtr<Profile> returnProfile = profileGenerator->profile(); @@ -99,10 +99,23 @@ PassRefPtr<Profile> Profiler::stopProfiling(ExecState* exec, const UString& titl return 0; } +void Profiler::stopProfiling(JSGlobalObject* origin) +{ + for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) { + ProfileGenerator* profileGenerator = m_currentProfiles[i].get(); + if (profileGenerator->origin() == origin) { + profileGenerator->stopProfiling(); + m_currentProfiles.remove(i); + if (!m_currentProfiles.size()) + s_sharedEnabledProfilerReference = 0; + } + } +} + static inline void dispatchFunctionToProfiles(ExecState* callerOrHandlerCallFrame, const Vector<RefPtr<ProfileGenerator> >& profiles, ProfileGenerator::ProfileFunction function, const CallIdentifier& callIdentifier, unsigned currentProfileTargetGroup) { for (size_t i = 0; i < profiles.size(); ++i) { - if (profiles[i]->profileGroup() == currentProfileTargetGroup || !profiles[i]->originatingGlobalExec()) + if (profiles[i]->profileGroup() == currentProfileTargetGroup || !profiles[i]->origin()) (profiles[i].get()->*function)(callerOrHandlerCallFrame, callIdentifier); } } diff --git a/Source/JavaScriptCore/profiler/Profiler.h b/Source/JavaScriptCore/profiler/Profiler.h index f88746d..86366c1 100644 --- a/Source/JavaScriptCore/profiler/Profiler.h +++ b/Source/JavaScriptCore/profiler/Profiler.h @@ -38,6 +38,7 @@ namespace JSC { class ExecState; class JSGlobalData; + class JSGlobalObject; class JSObject; class JSValue; class ProfileGenerator; @@ -57,6 +58,7 @@ namespace JSC { void startProfiling(ExecState*, const UString& title); PassRefPtr<Profile> stopProfiling(ExecState*, const UString& title); + void stopProfiling(JSGlobalObject*); void willExecute(ExecState* callerCallFrame, JSValue function); void willExecute(ExecState* callerCallFrame, const UString& sourceURL, int startingLineNumber); diff --git a/Source/JavaScriptCore/runtime/ArgList.cpp b/Source/JavaScriptCore/runtime/ArgList.cpp index 25a8916..f46d108 100644 --- a/Source/JavaScriptCore/runtime/ArgList.cpp +++ b/Source/JavaScriptCore/runtime/ArgList.cpp @@ -23,6 +23,7 @@ #include "JSValue.h" #include "JSCell.h" +#include "JSObject.h" #include "ScopeChain.h" using std::min; @@ -38,12 +39,12 @@ void ArgList::getSlice(int startIndex, ArgList& result) const result = ArgList(m_args + startIndex, m_argCount - startIndex); } -void MarkedArgumentBuffer::markLists(MarkStack& markStack, ListSet& markSet) +void MarkedArgumentBuffer::markLists(HeapRootMarker& heapRootMarker, ListSet& markSet) { ListSet::iterator end = markSet.end(); for (ListSet::iterator it = markSet.begin(); it != end; ++it) { MarkedArgumentBuffer* list = *it; - markStack.deprecatedAppendValues(list->m_buffer, list->m_size); + heapRootMarker.mark(reinterpret_cast<JSValue*>(list->m_buffer), list->m_size); } } @@ -55,8 +56,8 @@ void MarkedArgumentBuffer::slowAppend(JSValue v) // our Vector's inline capacity, though, our values move to the // heap, where they do need explicit marking. if (!m_markSet) { - // We can only register for explicit marking once we know which heap - // is the current one, i.e., when a non-immediate value is appended. + // FIXME: Even if v is not a JSCell*, if previous values in the buffer + // are, then they won't be marked! if (Heap* heap = Heap::heap(v)) { ListSet& markSet = heap->markListSet(); markSet.add(this); diff --git a/Source/JavaScriptCore/runtime/ArgList.h b/Source/JavaScriptCore/runtime/ArgList.h index 5564d5b..a794a04 100644 --- a/Source/JavaScriptCore/runtime/ArgList.h +++ b/Source/JavaScriptCore/runtime/ArgList.h @@ -141,7 +141,7 @@ namespace JSC { const_iterator begin() const { return m_buffer; } const_iterator end() const { return m_buffer + m_size; } - static void markLists(MarkStack&, ListSet&); + static void markLists(HeapRootMarker&, ListSet&); private: void slowAppend(JSValue); diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h index 007e0f1..950bb4e 100644 --- a/Source/JavaScriptCore/runtime/Arguments.h +++ b/Source/JavaScriptCore/runtime/Arguments.h @@ -92,9 +92,9 @@ namespace JSC { d->registers = &activation->registerAt(0); } - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: @@ -237,19 +237,17 @@ namespace JSC { // This JSActivation function is defined here so it can get at Arguments::setRegisters. inline void JSActivation::copyRegisters(JSGlobalData& globalData) { - ASSERT(!d()->registerArray); + ASSERT(!m_registerArray); - size_t numParametersMinusThis = d()->functionExecutable->parameterCount(); - size_t numVars = d()->functionExecutable->capturedVariableCount(); - size_t numLocals = numVars + numParametersMinusThis; + size_t numLocals = m_numCapturedVars + m_numParametersMinusThis; if (!numLocals) return; - int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize; + int registerOffset = m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize; size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize; - OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData, d()->registers - registerOffset, registerArraySize); + OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData, m_registers - registerOffset, registerArraySize); WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset; setRegisters(registers, registerArray.release()); } diff --git a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp index af2afc6..e0f4b23 100644 --- a/Source/JavaScriptCore/runtime/ArrayConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ArrayConstructor.cpp @@ -52,16 +52,18 @@ ArrayConstructor::ArrayConstructor(ExecState* exec, JSGlobalObject* globalObject static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args) { + JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject(); + // a single numeric argument denotes the array size (!) if (args.size() == 1 && args.at(0).isNumber()) { uint32_t n = args.at(0).toUInt32(exec); if (n != args.at(0).toNumber(exec)) return throwError(exec, createRangeError(exec, "Array size is not a small enough positive integer.")); - return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), n, CreateInitialized); + return new (exec) JSArray(globalObject->arrayStructure(), n, CreateInitialized); } // otherwise the array is constructed with the arguments in it - return new (exec) JSArray(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), args); + return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure(), args); } static EncodedJSValue JSC_HOST_CALL constructWithArrayConstructor(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index 488effd..fdbcd95 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -165,16 +165,20 @@ static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); + bool isRealArray = isJSArray(&exec->globalData(), thisValue); if (!isRealArray && !thisValue.inherits(&JSArray::s_info)) return throwVMTypeError(exec); JSArray* thisObj = asArray(thisValue); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + StringRecursionChecker checker(exec, thisObj); if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue()) return earlyReturnValue; - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned totalSize = length ? length - 1 : 0; #if OS(SYMBIAN) // Symbian has very limited stack size available. @@ -225,16 +229,20 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); + if (!thisValue.inherits(&JSArray::s_info)) return throwVMTypeError(exec); JSObject* thisObj = asArray(thisValue); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + StringRecursionChecker checker(exec, thisObj); if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue()) return earlyReturnValue; JSStringBuilder strBuffer; - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); for (unsigned k = 0; k < length; k++) { if (k >= 1) strBuffer.append(','); @@ -260,6 +268,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); StringRecursionChecker checker(exec, thisObj); if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue()) @@ -271,7 +282,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) if (!exec->argument(0).isUndefined()) separator = exec->argument(0).toString(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned k = 0; if (isJSArray(&exec->globalData(), thisObj)) { JSArray* array = asArray(thisObj); @@ -355,12 +365,16 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); + if (isJSArray(&exec->globalData(), thisValue)) return JSValue::encode(asArray(thisValue)->pop()); JSObject* thisObj = thisValue.toThisObject(exec); - JSValue result; unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + + JSValue result; if (length == 0) { putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length)); result = jsUndefined(); @@ -375,6 +389,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); + if (isJSArray(&exec->globalData(), thisValue) && exec->argumentCount() == 1) { JSArray* array = asArray(thisValue); array->push(exec, exec->argument(0)); @@ -383,6 +398,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec) JSObject* thisObj = thisValue.toThisObject(exec); unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + for (unsigned n = 0; n < exec->argumentCount(); n++) thisObj->put(exec, length + n, exec->argument(n)); length += exec->argumentCount(); @@ -394,8 +412,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - unsigned middle = length / 2; + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + unsigned middle = length / 2; for (unsigned k = 0; k < middle; k++) { unsigned lk1 = length - k - 1; JSValue obj2 = getProperty(exec, thisObj, lk1); @@ -420,6 +440,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec) JSValue result; unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + if (length == 0) { putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length)); result = jsUndefined(); @@ -451,6 +474,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec) JSValue result = resObj; unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length); unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length); @@ -466,6 +492,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (!length || exec->hadException()) + return JSValue::encode(thisObj); JSValue function = exec->argument(0); CallData callData; @@ -481,11 +510,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) return JSValue::encode(thisObj); } - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - - if (!length) - return JSValue::encode(thisObj); - // "Min" sort. Not the fastest, but definitely less code than heapsort // or quicksort, and much less swapping than bubblesort/insertionsort. for (unsigned i = 0; i < length - 1; ++i) { @@ -523,14 +547,16 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) { - JSObject* thisObj = exec->hostThisValue().toThisObject(exec); - // 15.4.4.12 + JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + if (!exec->argumentCount()) return JSValue::encode(constructEmptyArray(exec)); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length); unsigned deleteCount = length - begin; @@ -589,10 +615,13 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec) { - JSObject* thisObj = exec->hostThisValue().toThisObject(exec); - // 15.4.4.13 + + JSObject* thisObj = exec->hostThisValue().toThisObject(exec); unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + unsigned nrArgs = exec->argumentCount(); if ((nrArgs) && (length)) { if (isJSArray(&exec->globalData(), thisObj)) @@ -616,6 +645,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); JSValue function = exec->argument(0); CallData callData; @@ -627,7 +659,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) JSArray* resultArray = constructEmptyArray(exec); unsigned filterIndex = 0; - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned k = 0; if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { JSFunction* f = asFunction(function); @@ -674,6 +705,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); JSValue function = exec->argument(0); CallData callData; @@ -683,8 +717,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec) JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - JSArray* resultArray = constructEmptyArray(exec, length); unsigned k = 0; if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { @@ -731,6 +763,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); JSValue function = exec->argument(0); CallData callData; @@ -742,7 +777,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec) JSValue result = jsBoolean(true); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned k = 0; if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { JSFunction* f = asFunction(function); @@ -787,6 +821,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); JSValue function = exec->argument(0); CallData callData; @@ -796,7 +833,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec) JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned k = 0; if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { JSFunction* f = asFunction(function); @@ -832,6 +868,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); JSValue function = exec->argument(0); CallData callData; @@ -843,7 +882,6 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec) JSValue result = jsBoolean(false); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); unsigned k = 0; if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) { JSFunction* f = asFunction(function); @@ -885,7 +923,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); - + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + JSValue function = exec->argument(0); CallData callData; CallType callType = getCallData(function, callData); @@ -894,9 +935,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec) unsigned i = 0; JSValue rv; - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (!length && exec->argumentCount() == 1) return throwVMTypeError(exec); + JSArray* array = 0; if (isJSArray(&exec->globalData(), thisObj)) array = asArray(thisObj); @@ -955,7 +996,10 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec) { JSObject* thisObj = exec->hostThisValue().toThisObject(exec); - + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + JSValue function = exec->argument(0); CallData callData; CallType callType = getCallData(function, callData); @@ -964,9 +1008,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec) unsigned i = 0; JSValue rv; - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (!length && exec->argumentCount() == 1) return throwVMTypeError(exec); + JSArray* array = 0; if (isJSArray(&exec->globalData(), thisObj)) array = asArray(thisObj); @@ -1023,13 +1067,13 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec) { - // JavaScript 1.5 Extension by Mozilla - // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf + // 15.4.4.14 JSObject* thisObj = exec->hostThisValue().toThisObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length); JSValue searchElement = exec->argument(0); for (; index < length; ++index) { JSValue e = getProperty(exec, thisObj, index); @@ -1044,10 +1088,8 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec) EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec) { - // JavaScript 1.6 Extension by Mozilla - // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf + // 15.4.4.15 JSObject* thisObj = exec->hostThisValue().toThisObject(exec); - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); if (!length) return JSValue::encode(jsNumber(-1)); diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.h b/Source/JavaScriptCore/runtime/ArrayPrototype.h index e41d8ca..96641bd 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.h +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.h @@ -35,9 +35,9 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp index 21ef5bb..e5b0f3d 100644 --- a/Source/JavaScriptCore/runtime/BooleanConstructor.cpp +++ b/Source/JavaScriptCore/runtime/BooleanConstructor.cpp @@ -40,7 +40,7 @@ BooleanConstructor::BooleanConstructor(ExecState* exec, JSGlobalObject* globalOb // ECMA 15.6.2 JSObject* constructBoolean(ExecState* exec, const ArgList& args) { - BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), exec->lexicalGlobalObject()->booleanObjectStructure()); + BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), asInternalFunction(exec->callee())->globalObject()->booleanObjectStructure()); obj->setInternalValue(exec->globalData(), jsBoolean(args.at(0).toBoolean(exec))); return obj; } @@ -69,9 +69,9 @@ CallType BooleanConstructor::getCallData(CallData& callData) return CallTypeHost; } -JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSValue immediateBooleanValue) +JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSGlobalObject* globalObject, JSValue immediateBooleanValue) { - BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), exec->lexicalGlobalObject()->booleanObjectStructure()); + BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), globalObject->booleanObjectStructure()); obj->setInternalValue(exec->globalData(), immediateBooleanValue); return obj; } diff --git a/Source/JavaScriptCore/runtime/BooleanConstructor.h b/Source/JavaScriptCore/runtime/BooleanConstructor.h index 0f3efa7..2550b3b 100644 --- a/Source/JavaScriptCore/runtime/BooleanConstructor.h +++ b/Source/JavaScriptCore/runtime/BooleanConstructor.h @@ -36,7 +36,7 @@ namespace JSC { virtual CallType getCallData(CallData&); }; - JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSValue); + JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSGlobalObject*, JSValue); JSObject* constructBoolean(ExecState*, const ArgList&); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/BooleanObject.cpp b/Source/JavaScriptCore/runtime/BooleanObject.cpp index 16c4669..2945c0e 100644 --- a/Source/JavaScriptCore/runtime/BooleanObject.cpp +++ b/Source/JavaScriptCore/runtime/BooleanObject.cpp @@ -27,8 +27,8 @@ ASSERT_CLASS_FITS_IN_CELL(BooleanObject); const ClassInfo BooleanObject::s_info = { "Boolean", &JSWrapperObject::s_info, 0, 0 }; -BooleanObject::BooleanObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(globalData, structure) +BooleanObject::BooleanObject(JSGlobalData&, NonNullPassRefPtr<Structure> structure) + : JSWrapperObject(structure) { ASSERT(inherits(&s_info)); } diff --git a/Source/JavaScriptCore/runtime/BooleanObject.h b/Source/JavaScriptCore/runtime/BooleanObject.h index e2af0c2..ef2d403 100644 --- a/Source/JavaScriptCore/runtime/BooleanObject.h +++ b/Source/JavaScriptCore/runtime/BooleanObject.h @@ -31,9 +31,9 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } }; diff --git a/Source/JavaScriptCore/runtime/Completion.cpp b/Source/JavaScriptCore/runtime/Completion.cpp index 83d8bd8..ac19705 100644 --- a/Source/JavaScriptCore/runtime/Completion.cpp +++ b/Source/JavaScriptCore/runtime/Completion.cpp @@ -39,7 +39,7 @@ Completion checkSyntax(ExecState* exec, const SourceCode& source) JSLock lock(exec); ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable()); - RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source); + ProgramExecutable* program = ProgramExecutable::create(exec, source); JSObject* error = program->checkSyntax(exec); if (error) return Completion(Throw, error); @@ -52,14 +52,16 @@ Completion evaluate(ExecState* exec, ScopeChainNode* scopeChain, const SourceCod JSLock lock(exec); ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable()); - RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source); - JSObject* error = program->compile(exec, scopeChain); - if (error) - return Completion(Throw, error); + ProgramExecutable* program = ProgramExecutable::create(exec, source); + if (!program) { + JSValue exception = exec->globalData().exception; + exec->globalData().exception = JSValue(); + return Completion(Throw, exception); + } JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec); - JSValue result = exec->interpreter()->execute(program.get(), exec, scopeChain, thisObj); + JSValue result = exec->interpreter()->execute(program, exec, scopeChain, thisObj); if (exec->hadException()) { JSValue exception = exec->exception(); diff --git a/Source/JavaScriptCore/runtime/ConservativeSet.cpp b/Source/JavaScriptCore/runtime/ConservativeSet.cpp index bc8bd6d..8872023 100644 --- a/Source/JavaScriptCore/runtime/ConservativeSet.cpp +++ b/Source/JavaScriptCore/runtime/ConservativeSet.cpp @@ -33,33 +33,26 @@ inline bool isPointerAligned(void* p) return !((intptr_t)(p) & (sizeof(char*) - 1)); } -void ConservativeSet::grow() +void ConservativeRoots::grow() { size_t newCapacity = m_capacity == inlineCapacity ? nonInlineCapacity : m_capacity * 2; - DeprecatedPtr<JSCell>* newSet = static_cast<DeprecatedPtr<JSCell>*>(OSAllocator::reserveAndCommit(newCapacity * sizeof(JSCell*))); - memcpy(newSet, m_set, m_size * sizeof(JSCell*)); - if (m_set != m_inlineSet) - OSAllocator::decommitAndRelease(m_set, m_capacity * sizeof(JSCell*)); + JSCell** newRoots = static_cast<JSCell**>(OSAllocator::reserveAndCommit(newCapacity * sizeof(JSCell*))); + memcpy(newRoots, m_roots, m_size * sizeof(JSCell*)); + if (m_roots != m_inlineRoots) + OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*)); m_capacity = newCapacity; - m_set = newSet; + m_roots = newRoots; } -void ConservativeSet::add(void* begin, void* end) +void ConservativeRoots::add(void* begin, void* end) { ASSERT(begin <= end); ASSERT((static_cast<char*>(end) - static_cast<char*>(begin)) < 0x1000000); ASSERT(isPointerAligned(begin)); ASSERT(isPointerAligned(end)); - for (char** it = static_cast<char**>(begin); it != static_cast<char**>(end); ++it) { - if (!m_heap->contains(*it)) - continue; - - if (m_size == m_capacity) - grow(); - - m_set[m_size++] = reinterpret_cast<JSCell*>(*it); - } + for (char** it = static_cast<char**>(begin); it != static_cast<char**>(end); ++it) + add(*it); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ConservativeSet.h b/Source/JavaScriptCore/runtime/ConservativeSet.h index e7c2c4a..d078606 100644 --- a/Source/JavaScriptCore/runtime/ConservativeSet.h +++ b/Source/JavaScriptCore/runtime/ConservativeSet.h @@ -23,24 +23,30 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ConservativeSet_h -#define ConservativeSet_h +#ifndef ConservativeRoots_h +#define ConservativeRoots_h #include "Heap.h" -#include "MarkStack.h" +#include <wtf/OSAllocator.h> #include <wtf/Vector.h> namespace JSC { class JSCell; +class Heap; -class ConservativeSet { +// May contain duplicates. + +class ConservativeRoots { public: - ConservativeSet(Heap*); - ~ConservativeSet(); + ConservativeRoots(Heap*); + ~ConservativeRoots(); + void add(void*); void add(void* begin, void* end); - void mark(MarkStack&); + + size_t size(); + JSCell** roots(); private: static const size_t inlineCapacity = 128; @@ -49,32 +55,47 @@ private: void grow(); Heap* m_heap; - DeprecatedPtr<JSCell>* m_set; + JSCell** m_roots; size_t m_size; size_t m_capacity; - DeprecatedPtr<JSCell> m_inlineSet[inlineCapacity]; + JSCell* m_inlineRoots[inlineCapacity]; }; -inline ConservativeSet::ConservativeSet(Heap* heap) +inline ConservativeRoots::ConservativeRoots(Heap* heap) : m_heap(heap) - , m_set(m_inlineSet) + , m_roots(m_inlineRoots) , m_size(0) , m_capacity(inlineCapacity) { } -inline ConservativeSet::~ConservativeSet() +inline ConservativeRoots::~ConservativeRoots() +{ + if (m_roots != m_inlineRoots) + OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*)); +} + +inline void ConservativeRoots::add(void* p) +{ + if (!m_heap->contains(p)) + return; + + if (m_size == m_capacity) + grow(); + + m_roots[m_size++] = reinterpret_cast<JSCell*>(p); +} + +inline size_t ConservativeRoots::size() { - if (m_set != m_inlineSet) - OSAllocator::decommitAndRelease(m_set, m_capacity * sizeof(DeprecatedPtr<JSCell>*)); + return m_size; } -inline void ConservativeSet::mark(MarkStack& markStack) +inline JSCell** ConservativeRoots::roots() { - for (size_t i = 0; i < m_size; ++i) - markStack.append(&m_set[i]); + return m_roots; } } // namespace JSC -#endif // ConservativeSet_h +#endif // ConservativeRoots_h diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp index efaeb0f..0a06148 100644 --- a/Source/JavaScriptCore/runtime/DateConstructor.cpp +++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp @@ -70,7 +70,7 @@ DateConstructor::DateConstructor(ExecState* exec, JSGlobalObject* globalObject, } // ECMA 15.9.3 -JSObject* constructDate(ExecState* exec, const ArgList& args) +JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args) { int numArgs = args.size(); @@ -121,13 +121,13 @@ JSObject* constructDate(ExecState* exec, const ArgList& args) } } - return new (exec) DateInstance(exec, value); + return new (exec) DateInstance(exec, globalObject->dateStructure(), value); } static EncodedJSValue JSC_HOST_CALL constructWithDateConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructDate(exec, args)); + return JSValue::encode(constructDate(exec, asInternalFunction(exec->callee())->globalObject(), args)); } ConstructType DateConstructor::getConstructData(ConstructData& constructData) diff --git a/Source/JavaScriptCore/runtime/DateConstructor.h b/Source/JavaScriptCore/runtime/DateConstructor.h index 2adcd08..bd529f1 100644 --- a/Source/JavaScriptCore/runtime/DateConstructor.h +++ b/Source/JavaScriptCore/runtime/DateConstructor.h @@ -36,7 +36,7 @@ namespace JSC { virtual CallType getCallData(CallData&); }; - JSObject* constructDate(ExecState*, const ArgList&); + JSObject* constructDate(ExecState*, JSGlobalObject*, const ArgList&); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/DateConversion.cpp b/Source/JavaScriptCore/runtime/DateConversion.cpp index 597f1e9..1418876 100644 --- a/Source/JavaScriptCore/runtime/DateConversion.cpp +++ b/Source/JavaScriptCore/runtime/DateConversion.cpp @@ -44,6 +44,7 @@ #include "DateConversion.h" #include "CallFrame.h" +#include "JSObject.h" #include "ScopeChain.h" #include "UString.h" #include <wtf/DateMath.h> diff --git a/Source/JavaScriptCore/runtime/DateInstance.cpp b/Source/JavaScriptCore/runtime/DateInstance.cpp index 95d5dc2..74adda4 100644 --- a/Source/JavaScriptCore/runtime/DateInstance.cpp +++ b/Source/JavaScriptCore/runtime/DateInstance.cpp @@ -35,21 +35,14 @@ namespace JSC { const ClassInfo DateInstance::s_info = {"Date", &JSWrapperObject::s_info, 0, 0}; DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(exec->globalData(), structure) + : JSWrapperObject(structure) { ASSERT(inherits(&s_info)); setInternalValue(exec->globalData(), jsNaN()); } DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure, double time) - : JSWrapperObject(exec->globalData(), structure) -{ - ASSERT(inherits(&s_info)); - setInternalValue(exec->globalData(), jsNumber(timeClip(time))); -} - -DateInstance::DateInstance(ExecState* exec, double time) - : JSWrapperObject(exec->globalData(), exec->lexicalGlobalObject()->dateStructure()) + : JSWrapperObject(structure) { ASSERT(inherits(&s_info)); setInternalValue(exec->globalData(), jsNumber(timeClip(time))); diff --git a/Source/JavaScriptCore/runtime/DateInstance.h b/Source/JavaScriptCore/runtime/DateInstance.h index 627b9e7..d0dcf0b 100644 --- a/Source/JavaScriptCore/runtime/DateInstance.h +++ b/Source/JavaScriptCore/runtime/DateInstance.h @@ -31,7 +31,6 @@ namespace JSC { class DateInstance : public JSWrapperObject { public: - DateInstance(ExecState*, double); DateInstance(ExecState*, NonNullPassRefPtr<Structure>, double); explicit DateInstance(ExecState*, NonNullPassRefPtr<Structure>); @@ -53,14 +52,11 @@ namespace JSC { return calculateGregorianDateTimeUTC(exec); } - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } - protected: - static const unsigned StructureFlags = OverridesMarkChildren | JSWrapperObject::StructureFlags; - private: const GregorianDateTime* calculateGregorianDateTime(ExecState*) const; const GregorianDateTime* calculateGregorianDateTimeUTC(ExecState*) const; diff --git a/Source/JavaScriptCore/runtime/DatePrototype.h b/Source/JavaScriptCore/runtime/DatePrototype.h index dca90e3..0ebbedc 100644 --- a/Source/JavaScriptCore/runtime/DatePrototype.h +++ b/Source/JavaScriptCore/runtime/DatePrototype.h @@ -36,14 +36,16 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | DateInstance::StructureFlags; + COMPILE_ASSERT(!DateInstance::AnonymousSlotCount, DatePrototype_stomps_on_your_anonymous_slot); + static const unsigned AnonymousSlotCount = 1; }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ErrorConstructor.cpp b/Source/JavaScriptCore/runtime/ErrorConstructor.cpp index 2e53b95..7f4f82c 100644 --- a/Source/JavaScriptCore/runtime/ErrorConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ErrorConstructor.cpp @@ -42,7 +42,7 @@ ErrorConstructor::ErrorConstructor(ExecState* exec, JSGlobalObject* globalObject static EncodedJSValue JSC_HOST_CALL constructWithErrorConstructor(ExecState* exec) { JSValue message = exec->argumentCount() ? exec->argument(0) : jsUndefined(); - Structure* errorStructure = exec->lexicalGlobalObject()->errorStructure(); + Structure* errorStructure = asInternalFunction(exec->callee())->globalObject()->errorStructure(); return JSValue::encode(ErrorInstance::create(exec, errorStructure, message)); } @@ -55,7 +55,7 @@ ConstructType ErrorConstructor::getConstructData(ConstructData& constructData) static EncodedJSValue JSC_HOST_CALL callErrorConstructor(ExecState* exec) { JSValue message = exec->argumentCount() ? exec->argument(0) : jsUndefined(); - Structure* errorStructure = exec->lexicalGlobalObject()->errorStructure(); + Structure* errorStructure = asInternalFunction(exec->callee())->globalObject()->errorStructure(); return JSValue::encode(ErrorInstance::create(exec, errorStructure, message)); } diff --git a/Source/JavaScriptCore/runtime/ErrorInstance.h b/Source/JavaScriptCore/runtime/ErrorInstance.h index c1beef7..82dbf0f 100644 --- a/Source/JavaScriptCore/runtime/ErrorInstance.h +++ b/Source/JavaScriptCore/runtime/ErrorInstance.h @@ -29,9 +29,9 @@ namespace JSC { public: static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static ErrorInstance* create(JSGlobalData*, NonNullPassRefPtr<Structure>, const UString&); diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp index 607a2c2..a059ed2 100644 --- a/Source/JavaScriptCore/runtime/Executable.cpp +++ b/Source/JavaScriptCore/runtime/Executable.cpp @@ -33,6 +33,11 @@ #include "UStringBuilder.h" #include "Vector.h" +#if ENABLE(DFG_JIT) +#include "DFGByteCodeParser.h" +#include "DFGJITCompiler.h" +#endif + namespace JSC { NativeExecutable::~NativeExecutable() @@ -44,7 +49,7 @@ VPtrHackExecutable::~VPtrHackExecutable() } EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext) - : ScriptExecutable(exec, source, inStrictContext) + : ScriptExecutable(exec->globalData().evalExecutableStructure.get(), exec, source, inStrictContext) { } @@ -53,7 +58,7 @@ EvalExecutable::~EvalExecutable() } ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source) - : ScriptExecutable(exec, source, false) + : ScriptExecutable(exec->globalData().programExecutableStructure.get(), exec, source, false) { } @@ -62,7 +67,7 @@ ProgramExecutable::~ProgramExecutable() } FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine) - : ScriptExecutable(globalData, source, inStrictContext) + : ScriptExecutable(globalData->functionExecutableStructure.get(), globalData, source, inStrictContext) , m_numCapturedVariables(0) , m_forceUsesArguments(forceUsesArguments) , m_parameters(parameters) @@ -74,7 +79,7 @@ FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifie } FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine) - : ScriptExecutable(exec, source, inStrictContext) + : ScriptExecutable(exec->globalData().functionExecutableStructure.get(), exec, source, inStrictContext) , m_numCapturedVariables(0) , m_forceUsesArguments(forceUsesArguments) , m_parameters(parameters) @@ -85,9 +90,6 @@ FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, m_lastLine = lastLine; } -FunctionExecutable::~FunctionExecutable() -{ -} JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode) { @@ -127,6 +129,13 @@ JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scope return 0; } +void EvalExecutable::markChildren(MarkStack& markStack) +{ + ScriptExecutable::markChildren(markStack); + if (m_evalCodeBlock) + m_evalCodeBlock->markAggregate(markStack); +} + JSObject* ProgramExecutable::checkSyntax(ExecState* exec) { JSObject* exception = 0; @@ -178,6 +187,41 @@ JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* sc return 0; } +#if ENABLE(JIT) +static bool tryDFGCompile(JSGlobalData* globalData, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck) +{ +#if ENABLE(DFG_JIT) +#if ENABLE(DFG_JIT_RESTRICTIONS) + // FIXME: No flow control yet supported, don't bother scanning the bytecode if there are any jump targets. + // FIXME: temporarily disable property accesses until we fix regressions. + if (codeBlock->numberOfJumpTargets() || codeBlock->numberOfStructureStubInfos()) + return false; +#endif + + DFG::Graph dfg; + if (!parse(dfg, globalData, codeBlock)) + return false; + + DFG::JITCompiler dataFlowJIT(globalData, dfg, codeBlock); + dataFlowJIT.compileFunction(jitCode, jitCodeWithArityCheck); + return true; +#else + UNUSED_PARAM(globalData); + UNUSED_PARAM(codeBlock); + UNUSED_PARAM(jitCode); + UNUSED_PARAM(jitCodeWithArityCheck); + return false; +#endif +} +#endif + +void ProgramExecutable::markChildren(MarkStack& markStack) +{ + ScriptExecutable::markChildren(markStack); + if (m_programCodeBlock) + m_programCodeBlock->markAggregate(markStack); +} + JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode) { JSObject* exception = 0; @@ -212,7 +256,10 @@ JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChain #if ENABLE(JIT) if (exec->globalData().canUseJIT()) { - m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_codeBlockForCall.get(), &m_jitCodeForCallWithArityCheck); + bool dfgCompiled = tryDFGCompile(&exec->globalData(), m_codeBlockForCall.get(), m_jitCodeForCall, m_jitCodeForCallWithArityCheck); + if (!dfgCompiled) + m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_codeBlockForCall.get(), &m_jitCodeForCallWithArityCheck); + #if !ENABLE(OPCODE_SAMPLING) if (!BytecodeGenerator::dumpsGeneratedCode()) m_codeBlockForCall->discardBytecode(); @@ -268,8 +315,9 @@ JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, Scope return 0; } -void FunctionExecutable::markAggregate(MarkStack& markStack) +void FunctionExecutable::markChildren(MarkStack& markStack) { + ScriptExecutable::markChildren(markStack); if (m_codeBlockForCall) m_codeBlockForCall->markAggregate(markStack); if (m_codeBlockForConstruct) @@ -288,7 +336,7 @@ void FunctionExecutable::discardCode() #endif } -PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception) +FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception) { JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(lexicalGlobalObject, debugger, exec, source, 0, JSParseNormal, exception); diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h index b2565a0..f15df07 100644 --- a/Source/JavaScriptCore/runtime/Executable.h +++ b/Source/JavaScriptCore/runtime/Executable.h @@ -44,7 +44,7 @@ namespace JSC { struct ExceptionInfo; - class ExecutableBase : public RefCounted<ExecutableBase> { + class ExecutableBase : public JSCell { friend class JIT; protected: @@ -52,21 +52,23 @@ namespace JSC { static const int NUM_PARAMETERS_NOT_COMPILED = -1; public: - ExecutableBase(int numParameters) - : m_numParametersForCall(numParameters) + ExecutableBase(Structure* structure, int numParameters) + : JSCell(structure) + , m_numParametersForCall(numParameters) , m_numParametersForConstruct(numParameters) { } - virtual ~ExecutableBase() {} - bool isHostFunction() const { ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST)); return m_numParametersForCall == NUM_PARAMETERS_IS_HOST; } + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } + protected: + static const unsigned StructureFlags = 0; int m_numParametersForCall; int m_numParametersForConstruct; @@ -96,16 +98,16 @@ namespace JSC { friend class JIT; public: #if ENABLE(JIT) - static PassRefPtr<NativeExecutable> create(MacroAssemblerCodePtr callThunk, NativeFunction function, MacroAssemblerCodePtr constructThunk, NativeFunction constructor) + static NativeExecutable* create(JSGlobalData& globalData, MacroAssemblerCodePtr callThunk, NativeFunction function, MacroAssemblerCodePtr constructThunk, NativeFunction constructor) { if (!callThunk) - return adoptRef(new NativeExecutable(JITCode(), function, JITCode(), constructor)); - return adoptRef(new NativeExecutable(JITCode::HostFunction(callThunk), function, JITCode::HostFunction(constructThunk), constructor)); + return new (&globalData) NativeExecutable(globalData, JITCode(), function, JITCode(), constructor); + return new (&globalData) NativeExecutable(globalData, JITCode::HostFunction(callThunk), function, JITCode::HostFunction(constructThunk), constructor); } #else - static PassRefPtr<NativeExecutable> create(NativeFunction function, NativeFunction constructor) + static NativeExecutable* create(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor) { - return adoptRef(new NativeExecutable(function, constructor)); + return new (&globalData) NativeExecutable(globalData, function, constructor); } #endif @@ -115,8 +117,8 @@ namespace JSC { private: #if ENABLE(JIT) - NativeExecutable(JITCode callThunk, NativeFunction function, JITCode constructThunk, NativeFunction constructor) - : ExecutableBase(NUM_PARAMETERS_IS_HOST) + NativeExecutable(JSGlobalData& globalData, JITCode callThunk, NativeFunction function, JITCode constructThunk, NativeFunction constructor) + : ExecutableBase(globalData.executableStructure.get(), NUM_PARAMETERS_IS_HOST) , m_function(function) , m_constructor(constructor) { @@ -126,8 +128,8 @@ namespace JSC { m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall(); } #else - NativeExecutable(NativeFunction function, NativeFunction constructor) - : ExecutableBase(NUM_PARAMETERS_IS_HOST) + NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor) + : ExecutableBase(globalData.executableStructure.get(), NUM_PARAMETERS_IS_HOST) , m_function(function) , m_constructor(constructor) { @@ -142,8 +144,8 @@ namespace JSC { class VPtrHackExecutable : public ExecutableBase { public: - VPtrHackExecutable() - : ExecutableBase(NUM_PARAMETERS_IS_HOST) + VPtrHackExecutable(Structure* structure) + : ExecutableBase(structure, NUM_PARAMETERS_IS_HOST) { } @@ -152,8 +154,8 @@ namespace JSC { class ScriptExecutable : public ExecutableBase { public: - ScriptExecutable(JSGlobalData* globalData, const SourceCode& source, bool isInStrictContext) - : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED) + ScriptExecutable(Structure* structure, JSGlobalData* globalData, const SourceCode& source, bool isInStrictContext) + : ExecutableBase(structure, NUM_PARAMETERS_NOT_COMPILED) , m_source(source) , m_features(isInStrictContext ? StrictModeFeature : 0) { @@ -166,8 +168,8 @@ namespace JSC { #endif } - ScriptExecutable(ExecState* exec, const SourceCode& source, bool isInStrictContext) - : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED) + ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext) + : ExecutableBase(structure, NUM_PARAMETERS_NOT_COMPILED) , m_source(source) , m_features(isInStrictContext ? StrictModeFeature : 0) { @@ -214,6 +216,7 @@ namespace JSC { JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode) { + ASSERT(exec->globalData().dynamicGlobalObject); JSObject* error = 0; if (!m_evalCodeBlock) error = compileInternal(exec, scopeChainNode); @@ -227,7 +230,7 @@ namespace JSC { return *m_evalCodeBlock; } - static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source, bool isInStrictContext) { return adoptRef(new EvalExecutable(exec, source, isInStrictContext)); } + static EvalExecutable* create(ExecState* exec, const SourceCode& source, bool isInStrictContext) { return new (exec) EvalExecutable(exec, source, isInStrictContext); } #if ENABLE(JIT) JITCode& generatedJITCode() @@ -235,26 +238,30 @@ namespace JSC { return generatedJITCodeForCall(); } #endif + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } private: + static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags; EvalExecutable(ExecState*, const SourceCode&, bool); JSObject* compileInternal(ExecState*, ScopeChainNode*); + virtual void markChildren(MarkStack&); OwnPtr<EvalCodeBlock> m_evalCodeBlock; }; class ProgramExecutable : public ScriptExecutable { public: - static PassRefPtr<ProgramExecutable> create(ExecState* exec, const SourceCode& source) + static ProgramExecutable* create(ExecState* exec, const SourceCode& source) { - return adoptRef(new ProgramExecutable(exec, source)); + return new (exec) ProgramExecutable(exec, source); } ~ProgramExecutable(); JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode) { + ASSERT(exec->globalData().dynamicGlobalObject); JSObject* error = 0; if (!m_programCodeBlock) error = compileInternal(exec, scopeChainNode); @@ -276,11 +283,15 @@ namespace JSC { return generatedJITCodeForCall(); } #endif + + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } private: + static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags; ProgramExecutable(ExecState*, const SourceCode&); JSObject* compileInternal(ExecState*, ScopeChainNode*); + virtual void markChildren(MarkStack&); OwnPtr<ProgramCodeBlock> m_programCodeBlock; }; @@ -288,18 +299,16 @@ namespace JSC { class FunctionExecutable : public ScriptExecutable { friend class JIT; public: - static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) + static FunctionExecutable* create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) { - return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine)); + return new (exec) FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine); } - static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) + static FunctionExecutable* create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) { - return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine)); + return new (globalData) FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine); } - ~FunctionExecutable(); - JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain) { return new (exec) JSFunction(exec, this, scopeChain); @@ -318,6 +327,7 @@ namespace JSC { JSObject* compileForCall(ExecState* exec, ScopeChainNode* scopeChainNode) { + ASSERT(exec->globalData().dynamicGlobalObject); JSObject* error = 0; if (!m_codeBlockForCall) error = compileForCallInternal(exec, scopeChainNode); @@ -338,6 +348,7 @@ namespace JSC { JSObject* compileForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode) { + ASSERT(exec->globalData().dynamicGlobalObject); JSObject* error = 0; if (!m_codeBlockForConstruct) error = compileForConstructInternal(exec, scopeChainNode); @@ -363,8 +374,9 @@ namespace JSC { SharedSymbolTable* symbolTable() const { return m_symbolTable; } void discardCode(); - void markAggregate(MarkStack&); - static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception); + void markChildren(MarkStack&); + static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception); + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } private: FunctionExecutable(JSGlobalData*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine); @@ -372,7 +384,8 @@ namespace JSC { JSObject* compileForCallInternal(ExecState*, ScopeChainNode*); JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*); - + + static const unsigned StructureFlags = OverridesMarkChildren | ScriptExecutable::StructureFlags; unsigned m_numCapturedVariables : 31; bool m_forceUsesArguments : 1; diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp index e642594..a9f0a06 100644 --- a/Source/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/Source/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -49,7 +49,7 @@ FunctionConstructor::FunctionConstructor(ExecState* exec, JSGlobalObject* global static EncodedJSValue JSC_HOST_CALL constructWithFunctionConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructFunction(exec, args)); + return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args)); } ConstructType FunctionConstructor::getConstructData(ConstructData& constructData) @@ -61,7 +61,7 @@ ConstructType FunctionConstructor::getConstructData(ConstructData& constructData static EncodedJSValue JSC_HOST_CALL callFunctionConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructFunction(exec, args)); + return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args)); } // ECMA 15.3.1 The Function Constructor Called as a Function @@ -72,7 +72,7 @@ CallType FunctionConstructor::getCallData(CallData& callData) } // ECMA 15.3.2 The Function Constructor -JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber) +JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber) { // Functions need to have a space following the opening { due to for web compatibility // see https://bugs.webkit.org/show_bug.cgi?id=24350 @@ -96,11 +96,10 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi program = builder.toUString(); } - JSGlobalObject* globalObject = exec->lexicalGlobalObject(); JSGlobalData& globalData = globalObject->globalData(); SourceCode source = makeSource(program, sourceURL, lineNumber); JSObject* exception = 0; - RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception); + FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception); if (!function) { ASSERT(exception); return throwError(exec, exception); @@ -111,9 +110,9 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi } // ECMA 15.3.2 The Function Constructor -JSObject* constructFunction(ExecState* exec, const ArgList& args) +JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args) { - return constructFunction(exec, args, Identifier(exec, "anonymous"), UString(), 1); + return constructFunction(exec, globalObject, args, Identifier(exec, "anonymous"), UString(), 1); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/FunctionConstructor.h b/Source/JavaScriptCore/runtime/FunctionConstructor.h index 6af4861..7f21b20 100644 --- a/Source/JavaScriptCore/runtime/FunctionConstructor.h +++ b/Source/JavaScriptCore/runtime/FunctionConstructor.h @@ -36,8 +36,8 @@ namespace JSC { virtual CallType getCallData(CallData&); }; - JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber); - JSObject* constructFunction(ExecState*, const ArgList&); + JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber); + JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.h b/Source/JavaScriptCore/runtime/FunctionPrototype.h index fb0bb48..447f00b 100644 --- a/Source/JavaScriptCore/runtime/FunctionPrototype.h +++ b/Source/JavaScriptCore/runtime/FunctionPrototype.h @@ -30,9 +30,9 @@ namespace JSC { FunctionPrototype(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>); void addFunctionProperties(ExecState*, JSGlobalObject*, Structure* functionStructure, JSFunction** callFunction, JSFunction** applyFunction); - static PassRefPtr<Structure> createStructure(JSValue proto) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } private: diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp index a941cfa..2e878bf 100644 --- a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp +++ b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp @@ -33,6 +33,7 @@ #include "Heap.h" #include "JSGlobalData.h" #include "JSLock.h" +#include "JSObject.h" #include "ScopeChain.h" #include <wtf/RetainPtr.h> #include <wtf/WTFThreadData.h> diff --git a/Source/JavaScriptCore/runtime/GetterSetter.h b/Source/JavaScriptCore/runtime/GetterSetter.h index 68a8c70..8241275 100644 --- a/Source/JavaScriptCore/runtime/GetterSetter.h +++ b/Source/JavaScriptCore/runtime/GetterSetter.h @@ -47,9 +47,9 @@ namespace JSC { void setGetter(JSGlobalData& globalData, JSObject* getter) { m_getter.set(globalData, this, getter); } JSObject* setter() const { return m_setter.get(); } void setSetter(JSGlobalData& globalData, JSObject* setter) { m_setter.set(globalData, this, setter); } - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(GetterSetterType, OverridesMarkChildren), AnonymousSlotCount, 0); + return Structure::create(globalData, prototype, TypeInfo(GetterSetterType, OverridesMarkChildren), AnonymousSlotCount, 0); } private: virtual bool isGetterSetter() const; diff --git a/Source/JavaScriptCore/runtime/Heap.cpp b/Source/JavaScriptCore/runtime/Heap.cpp index c52bcfe..e3ef8bb 100644 --- a/Source/JavaScriptCore/runtime/Heap.cpp +++ b/Source/JavaScriptCore/runtime/Heap.cpp @@ -46,7 +46,7 @@ Heap::Heap(JSGlobalData* globalData) , m_markListSet(0) , m_activityCallback(DefaultGCActivityCallback::create(this)) , m_globalData(globalData) - , m_machineStackMarker(this) + , m_machineThreads(this) , m_markStack(globalData->jsArrayVPtr) , m_handleHeap(globalData) , m_extraCost(0) @@ -75,6 +75,10 @@ void Heap::destroy() // (and thus the global data) before other objects that may use the global data. RefPtr<JSGlobalData> protect(m_globalData); +#if ENABLE(JIT) + m_globalData->jitStubs->clearHostFunctionStubs(); +#endif + delete m_markListSet; m_markListSet = 0; m_markedSpace.clearMarks(); @@ -97,7 +101,7 @@ void Heap::reportExtraMemoryCostSlowCase(size_t cost) // if a large value survives one garbage collection, there is not much point to // collecting more frequently as long as it stays alive. - if (m_extraCost > maxExtraCost && m_extraCost > m_markedSpace.capacity() / 2) + if (m_extraCost > maxExtraCost && m_extraCost > m_markedSpace.highWaterMark() / 2) collectAllGarbage(); m_extraCost += cost; } @@ -147,11 +151,11 @@ bool Heap::unprotect(JSValue k) return m_protectedValues.remove(k.asCell()); } -void Heap::markProtectedObjects(MarkStack& markStack) +void Heap::markProtectedObjects(HeapRootMarker& heapRootMarker) { ProtectCountSet::iterator end = m_protectedValues.end(); for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) - markStack.deprecatedAppend(&it->first); + heapRootMarker.mark(&it->first); } void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector) @@ -165,7 +169,7 @@ void Heap::popTempSortVector(Vector<ValueStringPair>* tempVector) m_tempSortingVectors.removeLast(); } -void Heap::markTempSortVectors(MarkStack& markStack) +void Heap::markTempSortVectors(HeapRootMarker& heapRootMarker) { typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors; @@ -176,7 +180,7 @@ void Heap::markTempSortVectors(MarkStack& markStack) Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end(); for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) { if (vectorIt->first) - markStack.deprecatedAppend(&vectorIt->first); + heapRootMarker.mark(&vectorIt->first); } } } @@ -195,52 +199,52 @@ void Heap::markRoots() } #endif + void* dummy; + ASSERT(m_operationInProgress == NoOperation); if (m_operationInProgress != NoOperation) CRASH(); m_operationInProgress = Collection; - // We gather the conservative set before clearing mark bits, because + MarkStack& markStack = m_markStack; + HeapRootMarker heapRootMarker(markStack); + + // We gather conservative roots before clearing mark bits because // conservative gathering uses the mark bits from our last mark pass to // determine whether a reference is valid. - ConservativeSet conservativeSet(this); - m_machineStackMarker.markMachineStackConservatively(conservativeSet); - conservativeSet.add(registerFile().start(), registerFile().end()); + ConservativeRoots machineThreadRoots(this); + m_machineThreads.gatherConservativeRoots(machineThreadRoots, &dummy); + + ConservativeRoots registerFileRoots(this); + registerFile().gatherConservativeRoots(registerFileRoots); m_markedSpace.clearMarks(); - MarkStack& markStack = m_markStack; - conservativeSet.mark(markStack); + markStack.append(machineThreadRoots); markStack.drain(); - // Mark explicitly registered roots. - markProtectedObjects(markStack); + markStack.append(registerFileRoots); markStack.drain(); - - // Mark temporary vector for Array sorting - markTempSortVectors(markStack); + + markProtectedObjects(heapRootMarker); markStack.drain(); - HashSet<GlobalCodeBlock*>::const_iterator end = m_codeBlocks.end(); - for (HashSet<GlobalCodeBlock*>::const_iterator it = m_codeBlocks.begin(); it != end; ++it) - (*it)->markAggregate(markStack); + markTempSortVectors(heapRootMarker); markStack.drain(); - // Mark misc. other roots. if (m_markListSet && m_markListSet->size()) - MarkedArgumentBuffer::markLists(markStack, *m_markListSet); + MarkedArgumentBuffer::markLists(heapRootMarker, *m_markListSet); if (m_globalData->exception) - markStack.append(&m_globalData->exception); - if (m_globalData->firstStringifierToMark) - JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark); + heapRootMarker.mark(&m_globalData->exception); markStack.drain(); - m_handleHeap.markStrongHandles(markStack); + m_handleHeap.markStrongHandles(heapRootMarker); + m_handleStack.mark(heapRootMarker); // Mark the small strings cache last, since it will clear itself if nothing // else has marked it. - m_globalData->smallStrings.markChildren(markStack); + m_globalData->smallStrings.markChildren(heapRootMarker); markStack.drain(); markStack.compact(); @@ -371,7 +375,7 @@ void Heap::reset(SweepToggle sweepToggle) m_extraCost = 0; #if ENABLE(JSC_ZOMBIES) - sweep(); + sweepToggle = DoSweep; #endif if (sweepToggle == DoSweep) { @@ -379,7 +383,11 @@ void Heap::reset(SweepToggle sweepToggle) m_markedSpace.shrink(); } - size_t proportionalBytes = static_cast<size_t>(1.5 * m_markedSpace.size()); + // To avoid pathological GC churn in large heaps, we set the allocation high + // water mark to be proportional to the current size of the heap. The exact + // proportion is a bit arbitrary. A 2X multiplier gives a 1:1 (heap size : + // new bytes allocated) proportion, and seems to work well in benchmarks. + size_t proportionalBytes = 2 * m_markedSpace.size(); m_markedSpace.setHighWaterMark(max(proportionalBytes, minBytesPerCycle)); JAVASCRIPTCORE_GC_END(); diff --git a/Source/JavaScriptCore/runtime/Heap.h b/Source/JavaScriptCore/runtime/Heap.h index eb8af70..c2d3bac 100644 --- a/Source/JavaScriptCore/runtime/Heap.h +++ b/Source/JavaScriptCore/runtime/Heap.h @@ -23,6 +23,7 @@ #define Heap_h #include "HandleHeap.h" +#include "HandleStack.h" #include "MarkStack.h" #include "MarkedSpace.h" #include <wtf/Forward.h> @@ -33,6 +34,7 @@ namespace JSC { class GCActivityCallback; class GlobalCodeBlock; + class HeapRootMarker; class JSCell; class JSGlobalData; class JSValue; @@ -65,7 +67,7 @@ namespace JSC { JSGlobalData* globalData() const { return m_globalData; } MarkedSpace& markedSpace() { return m_markedSpace; } - MachineStackMarker& machineStackMarker() { return m_machineStackMarker; } + MachineThreads& machineThreads() { return m_machineThreads; } GCActivityCallback* activityCallback(); void setActivityCallback(PassOwnPtr<GCActivityCallback>); @@ -92,14 +94,15 @@ namespace JSC { void pushTempSortVector(Vector<ValueStringPair>*); void popTempSortVector(Vector<ValueStringPair>*); - - HashSet<GlobalCodeBlock*>& codeBlocks() { return m_codeBlocks; } - + HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; } template <typename Functor> void forEach(Functor&); HandleSlot allocateGlobalHandle() { return m_handleHeap.allocate(); } + HandleSlot allocateLocalHandle() { return m_handleStack.push(); } + + HandleStack* handleStack() { return &m_handleStack; } private: friend class JSGlobalData; @@ -111,8 +114,8 @@ namespace JSC { void reportExtraMemoryCostSlowCase(size_t); void markRoots(); - void markProtectedObjects(MarkStack&); - void markTempSortVectors(MarkStack&); + void markProtectedObjects(HeapRootMarker&); + void markTempSortVectors(HeapRootMarker&); enum SweepToggle { DoNotSweep, DoSweep }; void reset(SweepToggle); @@ -124,7 +127,6 @@ namespace JSC { ProtectCountSet m_protectedValues; Vector<Vector<ValueStringPair>* > m_tempSortingVectors; - HashSet<GlobalCodeBlock*> m_codeBlocks; HashSet<MarkedArgumentBuffer*>* m_markListSet; @@ -132,10 +134,11 @@ namespace JSC { JSGlobalData* m_globalData; - MachineStackMarker m_machineStackMarker; + MachineThreads m_machineThreads; MarkStack m_markStack; HandleHeap m_handleHeap; - + HandleStack m_handleStack; + size_t m_extraCost; }; diff --git a/Source/JavaScriptCore/runtime/Identifier.cpp b/Source/JavaScriptCore/runtime/Identifier.cpp index 3992418..4a99b19 100644 --- a/Source/JavaScriptCore/runtime/Identifier.cpp +++ b/Source/JavaScriptCore/runtime/Identifier.cpp @@ -22,6 +22,7 @@ #include "Identifier.h" #include "CallFrame.h" +#include "JSObject.h" #include "NumericStrings.h" #include "ScopeChain.h" #include <new> // for placement new @@ -90,7 +91,7 @@ bool Identifier::equal(const StringImpl* r, const UChar* s, unsigned length) struct IdentifierCStringTranslator { static unsigned hash(const char* c) { - return WTF::StringHasher::createHash<char>(c); + return StringHasher::computeHash<char>(c); } static bool equal(StringImpl* r, const char* s) @@ -150,7 +151,7 @@ struct UCharBuffer { struct IdentifierUCharBufferTranslator { static unsigned hash(const UCharBuffer& buf) { - return WTF::StringHasher::createHash<UChar>(buf.s, buf.length); + return StringHasher::computeHash<UChar>(buf.s, buf.length); } static bool equal(StringImpl* str, const UCharBuffer& buf) @@ -216,7 +217,7 @@ PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const UChar* s, { if (length == 1) { UChar c = s[0]; - if (c <= 0xFF) + if (c <= maxSingleCharacterString) return add(globalData, globalData->smallStrings.singleCharacterStringRep(c)); } if (!length) @@ -243,7 +244,7 @@ PassRefPtr<StringImpl> Identifier::addSlowCase(JSGlobalData* globalData, StringI if (r->length() == 1) { UChar c = r->characters()[0]; - if (c <= 0xFF) + if (c <= maxSingleCharacterString) r = globalData->smallStrings.singleCharacterStringRep(c); if (r->isIdentifier()) return r; diff --git a/Source/JavaScriptCore/runtime/InternalFunction.h b/Source/JavaScriptCore/runtime/InternalFunction.h index 8427b8c..08c98a5 100644 --- a/Source/JavaScriptCore/runtime/InternalFunction.h +++ b/Source/JavaScriptCore/runtime/InternalFunction.h @@ -39,9 +39,9 @@ namespace JSC { const UString displayName(ExecState*); const UString calculatedDisplayName(ExecState*); - static PassRefPtr<Structure> createStructure(JSValue proto) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: diff --git a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h index 43dd0d3..54fe909 100644 --- a/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h +++ b/Source/JavaScriptCore/runtime/JSAPIValueWrapper.h @@ -35,9 +35,9 @@ namespace JSC { virtual bool isAPIValueWrapper() const { return true; } - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren | OverridesGetPropertyNames), AnonymousSlotCount, 0); + return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesMarkChildren | OverridesGetPropertyNames), AnonymousSlotCount, 0); } diff --git a/Source/JavaScriptCore/runtime/JSActivation.cpp b/Source/JavaScriptCore/runtime/JSActivation.cpp index eb9c7c1..d0c50dd 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.cpp +++ b/Source/JavaScriptCore/runtime/JSActivation.cpp @@ -39,15 +39,23 @@ ASSERT_CLASS_FITS_IN_CELL(JSActivation); const ClassInfo JSActivation::s_info = { "JSActivation", &Base::s_info, 0, 0 }; -JSActivation::JSActivation(CallFrame* callFrame, NonNullPassRefPtr<FunctionExecutable> functionExecutable) - : Base(callFrame->globalData().activationStructure, new JSActivationData(functionExecutable, callFrame->registers())) +JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExecutable) + : Base(callFrame->globalData().activationStructure, functionExecutable->symbolTable(), callFrame->registers()) + , m_numParametersMinusThis(static_cast<int>(functionExecutable->parameterCount())) + , m_numCapturedVars(functionExecutable->capturedVariableCount()) + , m_requiresDynamicChecks(functionExecutable->usesEval()) + , m_argumentsRegister(functionExecutable->generatedBytecode().argumentsRegister()) { ASSERT(inherits(&s_info)); + + // We have to manually ref and deref the symbol table as JSVariableObject + // doesn't know about SharedSymbolTable + static_cast<SharedSymbolTable*>(m_symbolTable)->ref(); } JSActivation::~JSActivation() { - delete d(); + static_cast<SharedSymbolTable*>(m_symbolTable)->deref(); } void JSActivation::markChildren(MarkStack& markStack) @@ -55,30 +63,26 @@ void JSActivation::markChildren(MarkStack& markStack) Base::markChildren(markStack); // No need to mark our registers if they're still in the RegisterFile. - WriteBarrier<Unknown>* registerArray = d()->registerArray.get(); + WriteBarrier<Unknown>* registerArray = m_registerArray.get(); if (!registerArray) return; - size_t numParametersMinusThis = d()->functionExecutable->parameterCount(); - - size_t count = numParametersMinusThis; - markStack.appendValues(registerArray, count); - - size_t numVars = d()->functionExecutable->capturedVariableCount(); + markStack.appendValues(registerArray, m_numParametersMinusThis); // Skip the call frame, which sits between the parameters and vars. - markStack.appendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues); + markStack.appendValues(registerArray + m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize, m_numCapturedVars, MayContainNullValues); } inline bool JSActivation::symbolTableGet(const Identifier& propertyName, PropertySlot& slot) { SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); - if (!entry.isNull()) { - ASSERT(entry.getIndex() < static_cast<int>(d()->functionExecutable->capturedVariableCount())); - slot.setValue(registerAt(entry.getIndex()).get()); - return true; - } - return false; + if (entry.isNull()) + return false; + if (entry.getIndex() >= m_numCapturedVars) + return false; + + slot.setValue(registerAt(entry.getIndex()).get()); + return true; } inline bool JSActivation::symbolTablePut(JSGlobalData& globalData, const Identifier& propertyName, JSValue value) @@ -90,7 +94,9 @@ inline bool JSActivation::symbolTablePut(JSGlobalData& globalData, const Identif return false; if (entry.isReadOnly()) return true; - ASSERT(entry.getIndex() < static_cast<int>(d()->functionExecutable->capturedVariableCount())); + if (entry.getIndex() >= m_numCapturedVars) + return false; + registerAt(entry.getIndex()).set(globalData, this, value); return true; } @@ -99,9 +105,11 @@ void JSActivation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& prope { SymbolTable::const_iterator end = symbolTable().end(); for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) { - ASSERT(it->second.getIndex() < static_cast<int>(d()->functionExecutable->capturedVariableCount())); - if (!(it->second.getAttributes() & DontEnum) || (mode == IncludeDontEnumProperties)) - propertyNames.add(Identifier(exec, it->first.get())); + if (it->second.getAttributes() & DontEnum && mode != IncludeDontEnumProperties) + continue; + if (it->second.getIndex() >= m_numCapturedVars) + continue; + propertyNames.add(Identifier(exec, it->first.get())); } // Skip the JSVariableObject implementation of getOwnPropertyNames JSObject::getOwnPropertyNames(exec, propertyNames, mode); @@ -116,8 +124,9 @@ inline bool JSActivation::symbolTablePutWithAttributes(JSGlobalData& globalData, return false; SymbolTableEntry& entry = iter->second; ASSERT(!entry.isNull()); - if (entry.getIndex() >= static_cast<int>(d()->functionExecutable->capturedVariableCount())) + if (entry.getIndex() >= m_numCapturedVars) return false; + entry.setAttributes(attributes); registerAt(entry.getIndex()).set(globalData, this, value); return true; @@ -195,15 +204,15 @@ JSValue JSActivation::toStrictThisObject(ExecState*) const bool JSActivation::isDynamicScope(bool& requiresDynamicChecks) const { - requiresDynamicChecks = d()->functionExecutable->usesEval(); + requiresDynamicChecks = m_requiresDynamicChecks; return false; } JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, const Identifier&) { JSActivation* activation = asActivation(slotBase); - CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(activation->d()->registers)); - int argumentsRegister = activation->d()->functionExecutable->generatedBytecode().argumentsRegister(); + CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(activation->m_registers)); + int argumentsRegister = activation->m_argumentsRegister; if (JSValue arguments = callFrame->uncheckedR(argumentsRegister).jsValue()) return arguments; int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister); diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h index 6e04041..7463f47 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.h +++ b/Source/JavaScriptCore/runtime/JSActivation.h @@ -42,7 +42,7 @@ namespace JSC { class JSActivation : public JSVariableObject { typedef JSVariableObject Base; public: - JSActivation(CallFrame*, NonNullPassRefPtr<FunctionExecutable>); + JSActivation(CallFrame*, FunctionExecutable*); virtual ~JSActivation(); virtual void markChildren(MarkStack&); @@ -66,29 +66,12 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags; private: - struct JSActivationData : public JSVariableObjectData { - JSActivationData(NonNullPassRefPtr<FunctionExecutable> _functionExecutable, Register* registers) - : JSVariableObjectData(_functionExecutable->symbolTable(), registers) - , functionExecutable(_functionExecutable) - { - // We have to manually ref and deref the symbol table as JSVariableObjectData - // doesn't know about SharedSymbolTable - functionExecutable->symbolTable()->ref(); - } - ~JSActivationData() - { - static_cast<SharedSymbolTable*>(symbolTable)->deref(); - } - - RefPtr<FunctionExecutable> functionExecutable; - }; - bool symbolTableGet(const Identifier&, PropertySlot&); bool symbolTableGet(const Identifier&, PropertyDescriptor&); bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable); @@ -98,7 +81,10 @@ namespace JSC { static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&); NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter(); - JSActivationData* d() const { return static_cast<JSActivationData*>(JSVariableObject::d); } + int m_numParametersMinusThis; + int m_numCapturedVars : 31; + bool m_requiresDynamicChecks : 1; + int m_argumentsRegister; }; JSActivation* asActivation(JSValue); @@ -108,6 +94,11 @@ namespace JSC { ASSERT(asObject(value)->inherits(&JSActivation::s_info)); return static_cast<JSActivation*>(asObject(value)); } + + ALWAYS_INLINE JSActivation* Register::activation() const + { + return asActivation(jsValue()); + } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp index 822b84c..1d621fe 100644 --- a/Source/JavaScriptCore/runtime/JSArray.cpp +++ b/Source/JavaScriptCore/runtime/JSArray.cpp @@ -127,7 +127,7 @@ inline void JSArray::checkConsistency(ConsistencyCheckType) #endif JSArray::JSArray(VPtrStealingHackType) - : JSNonFinalObject(createStructure(jsNull())) + : JSNonFinalObject(Structure::create(Structure::VPtrStealingHack, &s_info)) { ASSERT(inherits(&s_info)); diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h index ede3c61..1a6eba8 100644 --- a/Source/JavaScriptCore/runtime/JSArray.h +++ b/Source/JavaScriptCore/runtime/JSArray.h @@ -58,7 +58,6 @@ namespace JSC { enum ArrayCreationMode { CreateCompact, CreateInitialized }; class JSArray : public JSNonFinalObject { - friend class JIT; friend class Walker; public: @@ -125,13 +124,23 @@ namespace JSC { void fillArgList(ExecState*, MarkedArgumentBuffer&); void copyToRegisters(ExecState*, Register*, uint32_t); - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } inline void markChildrenDirect(MarkStack& markStack); + static ptrdiff_t storageOffset() + { + return OBJECT_OFFSETOF(JSArray, m_storage); + } + + static ptrdiff_t vectorLengthOffset() + { + return OBJECT_OFFSETOF(JSArray, m_vectorLength); + } + protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags; virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); @@ -142,7 +151,7 @@ namespace JSC { void* subclassData() const; void setSubclassData(void*); - + private: bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&); void putSlowCase(ExecState*, unsigned propertyName, JSValue); @@ -174,11 +183,8 @@ namespace JSC { return asArray(value.asCell()); } - inline bool isJSArray(JSGlobalData* globalData, JSValue v) - { - return v.isCell() && v.asCell()->vptr() == globalData->jsArrayVPtr; - } 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 void JSArray::markChildrenDirect(MarkStack& markStack) { @@ -196,77 +202,6 @@ namespace JSC { } } - inline void MarkStack::markChildren(JSCell* cell) - { - ASSERT(Heap::isMarked(cell)); - if (!cell->structure()->typeInfo().overridesMarkChildren()) { -#ifdef NDEBUG - asObject(cell)->markChildrenDirect(*this); -#else - ASSERT(!m_isCheckingForDefaultMarkViolation); - m_isCheckingForDefaultMarkViolation = true; - cell->markChildren(*this); - ASSERT(m_isCheckingForDefaultMarkViolation); - m_isCheckingForDefaultMarkViolation = false; -#endif - return; - } - if (cell->vptr() == m_jsArrayVPtr) { - asArray(cell)->markChildrenDirect(*this); - return; - } - cell->markChildren(*this); - } - - inline void MarkStack::drain() - { -#if !ASSERT_DISABLED - ASSERT(!m_isDraining); - m_isDraining = true; -#endif - while (!m_markSets.isEmpty() || !m_values.isEmpty()) { - while (!m_markSets.isEmpty() && m_values.size() < 50) { - ASSERT(!m_markSets.isEmpty()); - MarkSet& current = m_markSets.last(); - ASSERT(current.m_values); - JSValue* end = current.m_end; - ASSERT(current.m_values); - ASSERT(current.m_values != end); - findNextUnmarkedNullValue: - ASSERT(current.m_values != end); - JSValue value = *current.m_values; - current.m_values++; - - JSCell* cell; - if (!value || !value.isCell() || Heap::testAndSetMarked(cell = value.asCell())) { - if (current.m_values == end) { - m_markSets.removeLast(); - continue; - } - goto findNextUnmarkedNullValue; - } - - if (cell->structure()->typeInfo().type() < CompoundType) { - if (current.m_values == end) { - m_markSets.removeLast(); - continue; - } - goto findNextUnmarkedNullValue; - } - - if (current.m_values == end) - m_markSets.removeLast(); - - markChildren(cell); - } - while (!m_values.isEmpty()) - markChildren(m_values.removeLast()); - } -#if !ASSERT_DISABLED - m_isDraining = false; -#endif - } - // 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. inline unsigned Identifier::toArrayIndex(bool& ok) const diff --git a/Source/JavaScriptCore/runtime/JSByteArray.cpp b/Source/JavaScriptCore/runtime/JSByteArray.cpp index ae735dc..fbaea1d 100644 --- a/Source/JavaScriptCore/runtime/JSByteArray.cpp +++ b/Source/JavaScriptCore/runtime/JSByteArray.cpp @@ -50,9 +50,9 @@ JSByteArray::~JSByteArray() #endif -PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype, const JSC::ClassInfo* classInfo) +PassRefPtr<Structure> JSByteArray::createStructure(JSGlobalData& globalData, JSValue prototype, const JSC::ClassInfo* classInfo) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, classInfo); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, classInfo); } bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) diff --git a/Source/JavaScriptCore/runtime/JSByteArray.h b/Source/JavaScriptCore/runtime/JSByteArray.h index 6e91594..e674958 100644 --- a/Source/JavaScriptCore/runtime/JSByteArray.h +++ b/Source/JavaScriptCore/runtime/JSByteArray.h @@ -76,7 +76,7 @@ namespace JSC { } JSByteArray(ExecState*, NonNullPassRefPtr<Structure>, WTF::ByteArray* storage); - static PassRefPtr<Structure> createStructure(JSValue prototype, const JSC::ClassInfo* = &s_defaultInfo); + static PassRefPtr<Structure> createStructure(JSGlobalData&, JSValue prototype, const JSC::ClassInfo* = &s_defaultInfo); virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&); @@ -102,7 +102,7 @@ namespace JSC { private: enum VPtrStealingHackType { VPtrStealingHack }; JSByteArray(VPtrStealingHackType) - : JSNonFinalObject(createStructure(jsNull())) + : JSNonFinalObject(Structure::create(Structure::VPtrStealingHack, &s_info)) { } diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp index 9acb777..ce7fe22 100644 --- a/Source/JavaScriptCore/runtime/JSCell.cpp +++ b/Source/JavaScriptCore/runtime/JSCell.cpp @@ -119,7 +119,7 @@ bool JSCell::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, P // This is not a general purpose implementation of getOwnPropertySlot. // It should only be called by JSValue::get. // It calls getPropertySlot, not getOwnPropertySlot. - JSObject* object = toObject(exec); + JSObject* object = toObject(exec, exec->lexicalGlobalObject()); slot.setBase(object); if (!object->getPropertySlot(exec, identifier, slot)) slot.setUndefined(); @@ -131,7 +131,7 @@ bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySl // This is not a general purpose implementation of getOwnPropertySlot. // It should only be called by JSValue::get. // It calls getPropertySlot, not getOwnPropertySlot. - JSObject* object = toObject(exec); + JSObject* object = toObject(exec, exec->lexicalGlobalObject()); slot.setBase(object); if (!object->getPropertySlot(exec, identifier, slot)) slot.setUndefined(); @@ -140,27 +140,27 @@ bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySl void JSCell::put(ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot) { - toObject(exec)->put(exec, identifier, value, slot); + toObject(exec, exec->lexicalGlobalObject())->put(exec, identifier, value, slot); } void JSCell::put(ExecState* exec, unsigned identifier, JSValue value) { - toObject(exec)->put(exec, identifier, value); + toObject(exec, exec->lexicalGlobalObject())->put(exec, identifier, value); } bool JSCell::deleteProperty(ExecState* exec, const Identifier& identifier) { - return toObject(exec)->deleteProperty(exec, identifier); + return toObject(exec, exec->lexicalGlobalObject())->deleteProperty(exec, identifier); } bool JSCell::deleteProperty(ExecState* exec, unsigned identifier) { - return toObject(exec)->deleteProperty(exec, identifier); + return toObject(exec, exec->lexicalGlobalObject())->deleteProperty(exec, identifier); } JSObject* JSCell::toThisObject(ExecState* exec) const { - return toObject(exec); + return toObject(exec, exec->lexicalGlobalObject()); } JSValue JSCell::getJSNumber() @@ -203,7 +203,7 @@ UString JSCell::toString(ExecState*) const return UString(); } -JSObject* JSCell::toObject(ExecState*) const +JSObject* JSCell::toObject(ExecState*, JSGlobalObject*) const { ASSERT_NOT_REACHED(); return 0; diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h index 7313d52..ab0e237 100644 --- a/Source/JavaScriptCore/runtime/JSCell.h +++ b/Source/JavaScriptCore/runtime/JSCell.h @@ -35,6 +35,8 @@ namespace JSC { + class JSGlobalObject; + #if COMPILER(MSVC) // If WTF_MAKE_NONCOPYABLE is applied to JSCell we end up with a bunch of // undefined references to the JSCell copy constructor and assignment operator @@ -53,10 +55,9 @@ namespace JSC { WTF_MAKE_NONCOPYABLE(JSCell); #endif + friend class ExecutableBase; friend class GetterSetter; friend class Heap; - friend class JIT; - friend class JSNumberCell; friend class JSObject; friend class JSPropertyNameIterator; friend class JSString; @@ -67,15 +68,16 @@ namespace JSC { friend class MarkedSpace; friend class MarkedBlock; friend class ScopeChainNode; + friend class StructureChain; private: explicit JSCell(Structure*); virtual ~JSCell(); public: - static PassRefPtr<Structure> createDummyStructure() + static PassRefPtr<Structure> createDummyStructure(JSGlobalData& globalData) { - return Structure::create(jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount, 0); + return Structure::create(globalData, jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount, 0); } // Querying the type. @@ -107,7 +109,7 @@ namespace JSC { virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; - virtual JSObject* toObject(ExecState*) const; + virtual JSObject* toObject(ExecState*, JSGlobalObject*) const; // Garbage collection. void* operator new(size_t, ExecState*); @@ -137,6 +139,16 @@ namespace JSC { // property names, we want a similar interface with appropriate optimizations.) bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); + static ptrdiff_t structureOffset() + { + return OBJECT_OFFSETOF(JSCell, m_structure); + } + + Structure* const * addressOfStructure() const + { + return &m_structure; + } + protected: static const unsigned AnonymousSlotCount = 0; @@ -203,6 +215,11 @@ namespace JSC { return isCell() ? asCell()->getString(exec) : UString(); } + template <typename Base> UString HandleConverter<Base, Unknown>::getString(ExecState* exec) const + { + return jsValue().getString(exec); + } + inline JSObject* JSValue::getObject() const { return isCell() ? asCell()->getObject() : 0; @@ -322,24 +339,19 @@ namespace JSC { inline JSObject* JSValue::toObject(ExecState* exec) const { - return isCell() ? asCell()->toObject(exec) : toObjectSlowCase(exec); + return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject()); } - inline JSObject* JSValue::toThisObject(ExecState* exec) const + inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject) const { - return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec); + return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject); } - - template <typename T> void MarkStack::append(DeprecatedPtr<T>* slot) + + inline JSObject* JSValue::toThisObject(ExecState* exec) const { - internalAppend(slot->get()); + return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec); } - template <typename T> void MarkStack::append(WriteBarrierBase<T>* slot) - { - internalAppend(slot->get()); - } - ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell) { ASSERT(!m_isCheckingForDefaultMarkViolation); @@ -350,31 +362,6 @@ namespace JSC { m_values.append(cell); } - ALWAYS_INLINE void MarkStack::deprecatedAppend(JSCell** value) - { - ASSERT(value); - internalAppend(*value); - } - - ALWAYS_INLINE void MarkStack::deprecatedAppend(JSValue* value) - { - ASSERT(value); - internalAppend(*value); - } - - ALWAYS_INLINE void MarkStack::deprecatedAppend(Register* value) - { - ASSERT(value); - internalAppend(value->jsValue()); - } - - ALWAYS_INLINE void MarkStack::internalAppend(JSValue value) - { - ASSERT(value); - if (value.isCell()) - internalAppend(value.asCell()); - } - inline Heap* Heap::heap(JSValue v) { if (!v.isCell()) @@ -411,8 +398,10 @@ namespace JSC { inline MarkedSpace::SizeClass& MarkedSpace::sizeClassFor(size_t bytes) { - ASSERT(bytes && bytes <= preciseCutoff); - return m_preciseSizeClasses[(bytes - 1) / preciseStep]; + ASSERT(bytes && bytes < maxCellSize); + if (bytes < preciseCutoff) + return m_preciseSizeClasses[(bytes - 1) / preciseStep]; + return m_impreciseSizeClasses[(bytes - 1) / impreciseStep]; } inline void* MarkedSpace::allocate(size_t bytes) diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp index 2ade441..dbfc606 100644 --- a/Source/JavaScriptCore/runtime/JSFunction.cpp +++ b/Source/JavaScriptCore/runtime/JSFunction.cpp @@ -56,16 +56,16 @@ bool JSFunction::isHostFunctionNonInline() const return isHostFunction(); } -JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure) +JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure, VPtrHackExecutable* executable) : Base(structure) - , m_executable(adoptRef(new VPtrHackExecutable())) { ASSERT(inherits(&s_info)); + m_executable.setWithoutWriteBarrier(executable); } -JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, PassRefPtr<NativeExecutable> thunk) +JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeExecutable* thunk) : Base(globalObject, structure) - , m_executable(thunk) + , m_executable(exec->globalData(), this, thunk) , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain()) { ASSERT(inherits(&s_info)); @@ -75,17 +75,20 @@ JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPas JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func) : Base(globalObject, structure) - , m_executable(exec->globalData().getHostFunction(func)) , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain()) { ASSERT(inherits(&s_info)); + // We separate out intialisation from setting the executable + // as getHostFunction may perform a GC allocation, so we have to be able to + // mark ourselves safely + m_executable.set(exec->globalData(), this, exec->globalData().getHostFunction(func)); putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum); putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum); } -JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode) +JSFunction::JSFunction(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChainNode) : Base(scopeChainNode->globalObject.get(), scopeChainNode->globalObject->functionStructure()) - , m_executable(executable) + , m_executable(exec->globalData(), this, executable) , m_scopeChain(exec->globalData(), this, scopeChainNode) { ASSERT(inherits(&s_info)); @@ -96,19 +99,6 @@ JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> ex JSFunction::~JSFunction() { ASSERT(vptr() == JSGlobalData::jsFunctionVPtr); - - // JIT code for other functions may have had calls linked directly to the code for this function; these links - // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once - // this memory is freed and may be reused (potentially for another, different JSFunction). - if (!isHostFunction()) { -#if ENABLE(JIT_OPTIMIZE_CALL) - ASSERT(m_executable); - if (jsExecutable()->isGeneratedForCall()) - jsExecutable()->generatedBytecodeForCall().unlinkCallers(); - if (jsExecutable()->isGeneratedForConstruct()) - jsExecutable()->generatedBytecodeForConstruct().unlinkCallers(); -#endif - } } static const char* StrictModeCallerAccessError = "Cannot access caller property of a strict mode function"; @@ -148,9 +138,13 @@ const UString JSFunction::calculatedDisplayName(ExecState* exec) void JSFunction::markChildren(MarkStack& markStack) { Base::markChildren(markStack); - if (!isHostFunction()) { - jsExecutable()->markAggregate(markStack); - markStack.append(&m_scopeChain); + + markStack.append(&m_scopeChain); + if (m_executable) { + // Delightful race condition: m_executable may not have been initialised + // if this is a host function, as the executable isn't necessarily created + // until after the function has been allocated. + markStack.append(&m_executable); } } diff --git a/Source/JavaScriptCore/runtime/JSFunction.h b/Source/JavaScriptCore/runtime/JSFunction.h index 089f42e..505b9de 100644 --- a/Source/JavaScriptCore/runtime/JSFunction.h +++ b/Source/JavaScriptCore/runtime/JSFunction.h @@ -34,6 +34,7 @@ namespace JSC { class JSActivation; class JSGlobalObject; class NativeExecutable; + class VPtrHackExecutable; EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*); @@ -45,8 +46,8 @@ namespace JSC { public: JSFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction); - JSFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int length, const Identifier&, PassRefPtr<NativeExecutable>); - JSFunction(ExecState*, NonNullPassRefPtr<FunctionExecutable>, ScopeChainNode*); + JSFunction(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeExecutable*); + JSFunction(ExecState*, FunctionExecutable*, ScopeChainNode*); virtual ~JSFunction(); const UString& name(ExecState*); @@ -72,9 +73,9 @@ namespace JSC { static JS_EXPORTDATA const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } NativeFunction nativeFunction(); @@ -86,7 +87,7 @@ namespace JSC { const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags; private: - JSFunction(NonNullPassRefPtr<Structure>); + JSFunction(NonNullPassRefPtr<Structure>, VPtrHackExecutable*); bool isHostFunctionNonInline() const; @@ -102,7 +103,7 @@ namespace JSC { static JSValue callerGetter(ExecState*, JSValue, const Identifier&); static JSValue lengthGetter(ExecState*, JSValue, const Identifier&); - RefPtr<ExecutableBase> m_executable; + WriteBarrier<ExecutableBase> m_executable; WriteBarrier<ScopeChainNode> m_scopeChain; }; diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp index e25040c..ee1829b 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp @@ -68,6 +68,27 @@ using namespace WTF; +namespace { + +using namespace JSC; + +class Recompiler { +public: + void operator()(JSCell*); +}; + +inline void Recompiler::operator()(JSCell* cell) +{ + if (!cell->inherits(&JSFunction::s_info)) + return; + JSFunction* function = asFunction(cell); + if (function->executable()->isHostFunction()) + return; + function->jsExecutable()->discardCode(); +} + +} // namespace + namespace JSC { extern JSC_CONST_HASHTABLE HashTable arrayTable; @@ -107,8 +128,12 @@ void JSGlobalData::storeVPtrs() jsString->~JSCell(); COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(storage), sizeof_JSFunction_must_be_less_than_storage); - JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull())); + char executableStorage[sizeof(VPtrHackExecutable)]; + RefPtr<Structure> executableStructure = Structure::create(Structure::VPtrStealingHack, 0); + JSCell* executable = new (executableStorage) VPtrHackExecutable(executableStructure.get()); + JSCell* jsFunction = new (storage) JSFunction(Structure::create(Structure::VPtrStealingHack, &JSFunction::s_info), static_cast<VPtrHackExecutable*>(executable)); JSGlobalData::jsFunctionVPtr = jsFunction->vptr(); + executable->~JSCell(); jsFunction->~JSCell(); } @@ -124,18 +149,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , regExpTable(fastNew<HashTable>(JSC::regExpTable)) , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable)) , stringTable(fastNew<HashTable>(JSC::stringTable)) - , activationStructure(JSActivation::createStructure(jsNull())) - , interruptedExecutionErrorStructure(JSNonFinalObject::createStructure(jsNull())) - , terminatedExecutionErrorStructure(JSNonFinalObject::createStructure(jsNull())) - , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull())) - , strictEvalActivationStructure(StrictEvalActivation::createStructure(jsNull())) - , stringStructure(JSString::createStructure(jsNull())) - , notAnObjectStructure(JSNotAnObject::createStructure(jsNull())) - , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull())) - , getterSetterStructure(GetterSetter::createStructure(jsNull())) - , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull())) - , scopeChainNodeStructure(ScopeChainNode::createStructure(jsNull())) - , dummyMarkableCellStructure(JSCell::createDummyStructure()) , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) , emptyList(new MarkedArgumentBuffer) @@ -145,7 +158,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , heap(this) , globalObjectCount(0) , dynamicGlobalObject(0) - , firstStringifierToMark(0) , cachedUTCOffset(NaN) , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth) , m_regExpCache(new RegExpCache(this)) @@ -156,6 +168,24 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , exclusiveThread(0) #endif { + activationStructure = JSActivation::createStructure(*this, jsNull()); + interruptedExecutionErrorStructure = JSNonFinalObject::createStructure(*this, jsNull()); + terminatedExecutionErrorStructure = JSNonFinalObject::createStructure(*this, jsNull()); + staticScopeStructure = JSStaticScopeObject::createStructure(*this, jsNull()); + strictEvalActivationStructure = StrictEvalActivation::createStructure(*this, jsNull()); + stringStructure = JSString::createStructure(*this, jsNull()); + notAnObjectStructure = JSNotAnObject::createStructure(*this, jsNull()); + propertyNameIteratorStructure = JSPropertyNameIterator::createStructure(*this, jsNull()); + getterSetterStructure = GetterSetter::createStructure(*this, jsNull()); + apiWrapperStructure = JSAPIValueWrapper::createStructure(*this, jsNull()); + scopeChainNodeStructure = ScopeChainNode::createStructure(*this, jsNull()); + executableStructure = ExecutableBase::createStructure(*this, jsNull()); + evalExecutableStructure = EvalExecutable::createStructure(*this, jsNull()); + programExecutableStructure = ProgramExecutable::createStructure(*this, jsNull()); + functionExecutableStructure = FunctionExecutable::createStructure(*this, jsNull()); + dummyMarkableCellStructure = JSCell::createDummyStructure(*this); + structureChainStructure = StructureChain::createStructure(*this, jsNull()); + interpreter = new Interpreter(*this); if (globalDataType == Default) m_stack = wtfThreadData().stack(); @@ -282,18 +312,18 @@ JSGlobalData*& JSGlobalData::sharedInstanceInternal() } #if ENABLE(JIT) -PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function) +NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function) { return jitStubs->hostFunctionStub(this, function); } -PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator) +NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator) { return jitStubs->hostFunctionStub(this, function, generator); } #else -PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function) +NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function) { - return NativeExecutable::create(function, callHostFunctionAsConstructor); + return NativeExecutable::create(*this, function, callHostFunctionAsConstructor); } #endif @@ -325,22 +355,6 @@ void JSGlobalData::dumpSampleData(ExecState* exec) interpreter->dumpSampleData(exec); } -class Recompiler { -public: - void operator()(JSCell*); -}; - -inline void Recompiler::operator()(JSCell* cell) -{ - if (!cell->inherits(&JSFunction::s_info)) - return; - JSFunction* function = asFunction(cell); - if (function->executable()->isHostFunction()) - return; - function->jsExecutable()->discardCode(); -} - - void JSGlobalData::recompileAllJSFunctions() { // If JavaScript is running, it's not safe to recompile, since we'll end diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h index ee3e067..34ea75d 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.h +++ b/Source/JavaScriptCore/runtime/JSGlobalData.h @@ -57,6 +57,7 @@ namespace JSC { class CodeBlock; class CommonIdentifiers; + class HandleStack; class IdentifierTable; class Interpreter; class JSGlobalObject; @@ -128,7 +129,7 @@ namespace JSC { #if ENABLE(JSC_MULTIPLE_THREADS) // Will start tracking threads that use the heap, which is resource-heavy. - void makeUsableFromMultipleThreads() { heap.machineStackMarker().makeUsableFromMultipleThreads(); } + void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); } #endif GlobalDataType globalDataType; @@ -155,7 +156,12 @@ namespace JSC { RefPtr<Structure> getterSetterStructure; RefPtr<Structure> apiWrapperStructure; RefPtr<Structure> scopeChainNodeStructure; + RefPtr<Structure> executableStructure; + RefPtr<Structure> evalExecutableStructure; + RefPtr<Structure> programExecutableStructure; + RefPtr<Structure> functionExecutableStructure; RefPtr<Structure> dummyMarkableCellStructure; + RefPtr<Structure> structureChainStructure; static void storeVPtrs(); static JS_EXPORTDATA void* jsArrayVPtr; @@ -199,15 +205,15 @@ namespace JSC { { return jitStubs->ctiStub(this, generator); } - PassRefPtr<NativeExecutable> getHostFunction(NativeFunction, ThunkGenerator); + NativeExecutable* getHostFunction(NativeFunction, ThunkGenerator); #endif - PassRefPtr<NativeExecutable> getHostFunction(NativeFunction); + NativeExecutable* getHostFunction(NativeFunction); TimeoutChecker timeoutChecker; Terminator terminator; Heap heap; - DeprecatedPtr<Unknown> exception; + JSValue exception; #if ENABLE(JIT) ReturnAddressPtr exceptionLocation; #endif @@ -219,8 +225,6 @@ namespace JSC { HashSet<JSObject*> stringRecursionCheckVisitedObjects; - Stringifier* firstStringifierToMark; - double cachedUTCOffset; DSTOffsetCache dstOffsetCache; @@ -255,6 +259,7 @@ namespace JSC { #endif void dumpRegExpTrace(); HandleSlot allocateGlobalHandle() { return heap.allocateGlobalHandle(); } + HandleSlot allocateLocalHandle() { return heap.allocateLocalHandle(); } private: JSGlobalData(GlobalDataType, ThreadStackType); diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp index 28fc07d..a2bbfbd 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -88,21 +88,21 @@ static inline void markIfNeeded(MarkStack& markStack, const RefPtr<Structure>& s { if (s && s->storedPrototype()) markStack.append(s->storedPrototypeSlot()); + if (s && *s->cachedPrototypeChainSlot()) + markStack.append(s->cachedPrototypeChainSlot()); } JSGlobalObject::~JSGlobalObject() { ASSERT(JSLock::currentThreadIsHoldingLock()); - if (d()->debugger) - d()->debugger->detach(this); + if (m_debugger) + m_debugger->detach(this); Profiler** profiler = Profiler::enabledProfilerReference(); if (UNLIKELY(*profiler != 0)) { - (*profiler)->stopProfiling(globalExec(), UString()); + (*profiler)->stopProfiling(this); } - - d()->destructor(d()); } void JSGlobalObject::init(JSObject* thisValue) @@ -111,14 +111,14 @@ void JSGlobalObject::init(JSObject* thisValue) structure()->disableSpecificFunctionTracking(); - d()->globalData = Heap::heap(this)->globalData(); - d()->globalScopeChain.set(*d()->globalData, this, new (d()->globalData.get()) ScopeChainNode(0, this, d()->globalData.get(), this, thisValue)); + m_globalData = Heap::heap(this)->globalData(); + m_globalScopeChain.set(*m_globalData, this, new (m_globalData.get()) ScopeChainNode(0, this, m_globalData.get(), this, thisValue)); - JSGlobalObject::globalExec()->init(0, 0, d()->globalScopeChain.get(), CallFrame::noCaller(), 0, 0); + JSGlobalObject::globalExec()->init(0, 0, m_globalScopeChain.get(), CallFrame::noCaller(), 0, 0); - d()->debugger = 0; + m_debugger = 0; - d()->profileGroup = 0; + m_profileGroup = 0; reset(prototype()); } @@ -177,80 +177,80 @@ void JSGlobalObject::reset(JSValue prototype) // Prototypes - d()->functionPrototype.set(exec->globalData(), this, new (exec) FunctionPrototype(exec, this, FunctionPrototype::createStructure(jsNull()))); // The real prototype will be set once ObjectPrototype is created. - d()->functionStructure = JSFunction::createStructure(d()->functionPrototype.get()); - d()->internalFunctionStructure = InternalFunction::createStructure(d()->functionPrototype.get()); + m_functionPrototype.set(exec->globalData(), this, new (exec) FunctionPrototype(exec, this, FunctionPrototype::createStructure(exec->globalData(), jsNull()))); // The real prototype will be set once ObjectPrototype is created. + m_functionStructure = JSFunction::createStructure(exec->globalData(), m_functionPrototype.get()); + m_internalFunctionStructure = InternalFunction::createStructure(exec->globalData(), m_functionPrototype.get()); JSFunction* callFunction = 0; JSFunction* applyFunction = 0; - d()->functionPrototype->addFunctionProperties(exec, this, d()->functionStructure.get(), &callFunction, &applyFunction); - d()->callFunction.set(exec->globalData(), this, callFunction); - d()->applyFunction.set(exec->globalData(), this, applyFunction); - d()->objectPrototype.set(exec->globalData(), this, new (exec) ObjectPrototype(exec, this, ObjectPrototype::createStructure(jsNull()), d()->functionStructure.get())); - d()->functionPrototype->structure()->setPrototypeWithoutTransition(d()->objectPrototype.get()); + m_functionPrototype->addFunctionProperties(exec, this, m_functionStructure.get(), &callFunction, &applyFunction); + m_callFunction.set(exec->globalData(), this, callFunction); + m_applyFunction.set(exec->globalData(), this, applyFunction); + m_objectPrototype.set(exec->globalData(), this, new (exec) ObjectPrototype(exec, this, ObjectPrototype::createStructure(exec->globalData(), jsNull()), m_functionStructure.get())); + m_functionPrototype->structure()->setPrototypeWithoutTransition(m_objectPrototype.get()); - d()->emptyObjectStructure = d()->objectPrototype->inheritorID(); + m_emptyObjectStructure = m_objectPrototype->inheritorID(exec->globalData()); - d()->callbackFunctionStructure = JSCallbackFunction::createStructure(d()->functionPrototype.get()); - d()->argumentsStructure = Arguments::createStructure(d()->objectPrototype.get()); - d()->callbackConstructorStructure = JSCallbackConstructor::createStructure(d()->objectPrototype.get()); - d()->callbackObjectStructure = JSCallbackObject<JSObjectWithGlobalObject>::createStructure(d()->objectPrototype.get()); + m_callbackFunctionStructure = JSCallbackFunction::createStructure(exec->globalData(), m_functionPrototype.get()); + m_argumentsStructure = Arguments::createStructure(exec->globalData(), m_objectPrototype.get()); + m_callbackConstructorStructure = JSCallbackConstructor::createStructure(exec->globalData(), m_objectPrototype.get()); + m_callbackObjectStructure = JSCallbackObject<JSObjectWithGlobalObject>::createStructure(exec->globalData(), m_objectPrototype.get()); - d()->arrayPrototype.set(exec->globalData(), this, new (exec) ArrayPrototype(this, ArrayPrototype::createStructure(d()->objectPrototype.get()))); - d()->arrayStructure = JSArray::createStructure(d()->arrayPrototype.get()); - d()->regExpMatchesArrayStructure = RegExpMatchesArray::createStructure(d()->arrayPrototype.get()); + m_arrayPrototype.set(exec->globalData(), this, new (exec) ArrayPrototype(this, ArrayPrototype::createStructure(exec->globalData(), m_objectPrototype.get()))); + m_arrayStructure = JSArray::createStructure(exec->globalData(), m_arrayPrototype.get()); + m_regExpMatchesArrayStructure = RegExpMatchesArray::createStructure(exec->globalData(), m_arrayPrototype.get()); - d()->stringPrototype.set(exec->globalData(), this, new (exec) StringPrototype(exec, this, StringPrototype::createStructure(d()->objectPrototype.get()))); - d()->stringObjectStructure = StringObject::createStructure(d()->stringPrototype.get()); + m_stringPrototype.set(exec->globalData(), this, new (exec) StringPrototype(exec, this, StringPrototype::createStructure(exec->globalData(), m_objectPrototype.get()))); + m_stringObjectStructure = StringObject::createStructure(exec->globalData(), m_stringPrototype.get()); - d()->booleanPrototype.set(exec->globalData(), this, new (exec) BooleanPrototype(exec, this, BooleanPrototype::createStructure(d()->objectPrototype.get()), d()->functionStructure.get())); - d()->booleanObjectStructure = BooleanObject::createStructure(d()->booleanPrototype.get()); + m_booleanPrototype.set(exec->globalData(), this, new (exec) BooleanPrototype(exec, this, BooleanPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), m_functionStructure.get())); + m_booleanObjectStructure = BooleanObject::createStructure(exec->globalData(), m_booleanPrototype.get()); - d()->numberPrototype.set(exec->globalData(), this, new (exec) NumberPrototype(exec, this, NumberPrototype::createStructure(d()->objectPrototype.get()), d()->functionStructure.get())); - d()->numberObjectStructure = NumberObject::createStructure(d()->numberPrototype.get()); + m_numberPrototype.set(exec->globalData(), this, new (exec) NumberPrototype(exec, this, NumberPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), m_functionStructure.get())); + m_numberObjectStructure = NumberObject::createStructure(exec->globalData(), m_numberPrototype.get()); - d()->datePrototype.set(exec->globalData(), this, new (exec) DatePrototype(exec, this, DatePrototype::createStructure(d()->objectPrototype.get()))); - d()->dateStructure = DateInstance::createStructure(d()->datePrototype.get()); + m_datePrototype.set(exec->globalData(), this, new (exec) DatePrototype(exec, this, DatePrototype::createStructure(exec->globalData(), m_objectPrototype.get()))); + m_dateStructure = DateInstance::createStructure(exec->globalData(), m_datePrototype.get()); - d()->regExpPrototype.set(exec->globalData(), this, new (exec) RegExpPrototype(exec, this, RegExpPrototype::createStructure(d()->objectPrototype.get()), d()->functionStructure.get())); - d()->regExpStructure = RegExpObject::createStructure(d()->regExpPrototype.get()); + m_regExpPrototype.set(exec->globalData(), this, new (exec) RegExpPrototype(exec, this, RegExpPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), m_functionStructure.get())); + m_regExpStructure = RegExpObject::createStructure(exec->globalData(), m_regExpPrototype.get()); - d()->methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec)); + m_methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec)); - ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, this, ErrorPrototype::createStructure(d()->objectPrototype.get()), d()->functionStructure.get()); - d()->errorStructure = ErrorInstance::createStructure(errorPrototype); + ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, this, ErrorPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), m_functionStructure.get()); + m_errorStructure = ErrorInstance::createStructure(exec->globalData(), errorPrototype); // Constructors - JSCell* objectConstructor = new (exec) ObjectConstructor(exec, this, ObjectConstructor::createStructure(d()->functionPrototype.get()), d()->objectPrototype.get()); - JSCell* functionConstructor = new (exec) FunctionConstructor(exec, this, FunctionConstructor::createStructure(d()->functionPrototype.get()), d()->functionPrototype.get()); - JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, this, ArrayConstructor::createStructure(d()->functionPrototype.get()), d()->arrayPrototype.get(), d()->functionStructure.get()); - JSCell* stringConstructor = new (exec) StringConstructor(exec, this, StringConstructor::createStructure(d()->functionPrototype.get()), d()->functionStructure.get(), d()->stringPrototype.get()); - JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, this, BooleanConstructor::createStructure(d()->functionPrototype.get()), d()->booleanPrototype.get()); - JSCell* numberConstructor = new (exec) NumberConstructor(exec, this, NumberConstructor::createStructure(d()->functionPrototype.get()), d()->numberPrototype.get()); - JSCell* dateConstructor = new (exec) DateConstructor(exec, this, DateConstructor::createStructure(d()->functionPrototype.get()), d()->functionStructure.get(), d()->datePrototype.get()); - - d()->regExpConstructor.set(exec->globalData(), this, new (exec) RegExpConstructor(exec, this, RegExpConstructor::createStructure(d()->functionPrototype.get()), d()->regExpPrototype.get())); - - d()->errorConstructor.set(exec->globalData(), this, new (exec) ErrorConstructor(exec, this, ErrorConstructor::createStructure(d()->functionPrototype.get()), errorPrototype)); - - RefPtr<Structure> nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(errorPrototype); - RefPtr<Structure> nativeErrorStructure = NativeErrorConstructor::createStructure(d()->functionPrototype.get()); - d()->evalErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "EvalError")); - d()->rangeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "RangeError")); - d()->referenceErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "ReferenceError")); - d()->syntaxErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "SyntaxError")); - d()->typeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "TypeError")); - d()->URIErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "URIError")); - - d()->objectPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, objectConstructor, DontEnum); - d()->functionPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, functionConstructor, DontEnum); - d()->arrayPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, arrayConstructor, DontEnum); - d()->booleanPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, booleanConstructor, DontEnum); - d()->stringPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, stringConstructor, DontEnum); - d()->numberPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, numberConstructor, DontEnum); - d()->datePrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, dateConstructor, DontEnum); - d()->regExpPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, d()->regExpConstructor.get(), DontEnum); - errorPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, d()->errorConstructor.get(), DontEnum); + JSCell* objectConstructor = new (exec) ObjectConstructor(exec, this, ObjectConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_objectPrototype.get()); + JSCell* functionConstructor = new (exec) FunctionConstructor(exec, this, FunctionConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_functionPrototype.get()); + JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, this, ArrayConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_arrayPrototype.get(), m_functionStructure.get()); + JSCell* stringConstructor = new (exec) StringConstructor(exec, this, StringConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_functionStructure.get(), m_stringPrototype.get()); + JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, this, BooleanConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_booleanPrototype.get()); + JSCell* numberConstructor = new (exec) NumberConstructor(exec, this, NumberConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_numberPrototype.get()); + JSCell* dateConstructor = new (exec) DateConstructor(exec, this, DateConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_functionStructure.get(), m_datePrototype.get()); + + m_regExpConstructor.set(exec->globalData(), this, new (exec) RegExpConstructor(exec, this, RegExpConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_regExpPrototype.get())); + + m_errorConstructor.set(exec->globalData(), this, new (exec) ErrorConstructor(exec, this, ErrorConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), errorPrototype)); + + RefPtr<Structure> nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(exec->globalData(), errorPrototype); + RefPtr<Structure> nativeErrorStructure = NativeErrorConstructor::createStructure(exec->globalData(), m_functionPrototype.get()); + m_evalErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "EvalError")); + m_rangeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "RangeError")); + m_referenceErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "ReferenceError")); + m_syntaxErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "SyntaxError")); + m_typeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "TypeError")); + m_URIErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "URIError")); + + m_objectPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, objectConstructor, DontEnum); + m_functionPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, functionConstructor, DontEnum); + m_arrayPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, arrayConstructor, DontEnum); + m_booleanPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, booleanConstructor, DontEnum); + m_stringPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, stringConstructor, DontEnum); + m_numberPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, numberConstructor, DontEnum); + m_datePrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, dateConstructor, DontEnum); + m_regExpPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_regExpConstructor.get(), DontEnum); + errorPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_errorConstructor.get(), DontEnum); // Set global constructors @@ -263,42 +263,42 @@ void JSGlobalObject::reset(JSValue prototype) putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "String"), stringConstructor, DontEnum); putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Number"), numberConstructor, DontEnum); putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Date"), dateConstructor, DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RegExp"), d()->regExpConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Error"), d()->errorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "EvalError"), d()->evalErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RangeError"), d()->rangeErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "TypeError"), d()->typeErrorConstructor.get(), DontEnum); - putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "URIError"), d()->URIErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RegExp"), m_regExpConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Error"), m_errorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "EvalError"), m_evalErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RangeError"), m_rangeErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "ReferenceError"), m_referenceErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "SyntaxError"), m_syntaxErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "TypeError"), m_typeErrorConstructor.get(), DontEnum); + putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "URIError"), m_URIErrorConstructor.get(), DontEnum); // Set global values. GlobalPropertyInfo staticGlobals[] = { - GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, this, MathObject::createStructure(d()->objectPrototype.get())), DontEnum | DontDelete), + GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, this, MathObject::createStructure(exec->globalData(), m_objectPrototype.get())), DontEnum | DontDelete), GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(), DontEnum | DontDelete | ReadOnly), GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(Inf), DontEnum | DontDelete | ReadOnly), GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete | ReadOnly), - GlobalPropertyInfo(Identifier(exec, "JSON"), new (exec) JSONObject(this, JSONObject::createStructure(d()->objectPrototype.get())), DontEnum | DontDelete) + GlobalPropertyInfo(Identifier(exec, "JSON"), new (exec) JSONObject(this, JSONObject::createStructure(exec->globalData(), m_objectPrototype.get())), DontEnum | DontDelete) }; addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals)); // Set global functions. - d()->evalFunction.set(exec->globalData(), this, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, exec->propertyNames().eval, globalFuncEval)); - putDirectFunctionWithoutTransition(exec, d()->evalFunction.get(), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "isNaN"), globalFuncIsNaN), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "isFinite"), globalFuncIsFinite), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "escape"), globalFuncEscape), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "unescape"), globalFuncUnescape), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "decodeURI"), globalFuncDecodeURI), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "decodeURIComponent"), globalFuncDecodeURIComponent), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "encodeURIComponent"), globalFuncEncodeURIComponent), DontEnum); + m_evalFunction.set(exec->globalData(), this, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, exec->propertyNames().eval, globalFuncEval)); + putDirectFunctionWithoutTransition(exec, m_evalFunction.get(), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "isNaN"), globalFuncIsNaN), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "isFinite"), globalFuncIsFinite), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "escape"), globalFuncEscape), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "unescape"), globalFuncUnescape), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "decodeURI"), globalFuncDecodeURI), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "decodeURIComponent"), globalFuncDecodeURIComponent), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "encodeURIComponent"), globalFuncEncodeURIComponent), DontEnum); #ifndef NDEBUG - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, d()->functionStructure.get(), 1, Identifier(exec, "jscprint"), globalFuncJSCPrint), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, Identifier(exec, "jscprint"), globalFuncJSCPrint), DontEnum); #endif resetPrototype(prototype); @@ -310,7 +310,7 @@ void JSGlobalObject::resetPrototype(JSValue prototype) setPrototype(prototype); JSObject* oldLastInPrototypeChain = lastInPrototypeChain(this); - JSObject* objectPrototype = d()->objectPrototype.get(); + JSObject* objectPrototype = m_objectPrototype.get(); if (oldLastInPrototypeChain != objectPrototype) oldLastInPrototypeChain->setPrototype(objectPrototype); } @@ -318,67 +318,63 @@ void JSGlobalObject::resetPrototype(JSValue prototype) void JSGlobalObject::markChildren(MarkStack& markStack) { JSVariableObject::markChildren(markStack); - - markIfNeeded(markStack, &d()->globalScopeChain); - - markIfNeeded(markStack, &d()->regExpConstructor); - markIfNeeded(markStack, &d()->errorConstructor); - markIfNeeded(markStack, &d()->evalErrorConstructor); - markIfNeeded(markStack, &d()->rangeErrorConstructor); - markIfNeeded(markStack, &d()->referenceErrorConstructor); - markIfNeeded(markStack, &d()->syntaxErrorConstructor); - markIfNeeded(markStack, &d()->typeErrorConstructor); - markIfNeeded(markStack, &d()->URIErrorConstructor); - - markIfNeeded(markStack, &d()->evalFunction); - markIfNeeded(markStack, &d()->callFunction); - markIfNeeded(markStack, &d()->applyFunction); - - markIfNeeded(markStack, &d()->objectPrototype); - markIfNeeded(markStack, &d()->functionPrototype); - markIfNeeded(markStack, &d()->arrayPrototype); - markIfNeeded(markStack, &d()->booleanPrototype); - markIfNeeded(markStack, &d()->stringPrototype); - markIfNeeded(markStack, &d()->numberPrototype); - markIfNeeded(markStack, &d()->datePrototype); - markIfNeeded(markStack, &d()->regExpPrototype); - - markIfNeeded(markStack, &d()->methodCallDummy); - - markIfNeeded(markStack, d()->errorStructure); - markIfNeeded(markStack, d()->argumentsStructure); - markIfNeeded(markStack, d()->arrayStructure); - markIfNeeded(markStack, d()->booleanObjectStructure); - markIfNeeded(markStack, d()->callbackConstructorStructure); - markIfNeeded(markStack, d()->callbackFunctionStructure); - markIfNeeded(markStack, d()->callbackObjectStructure); - markIfNeeded(markStack, d()->dateStructure); - markIfNeeded(markStack, d()->emptyObjectStructure); - markIfNeeded(markStack, d()->errorStructure); - markIfNeeded(markStack, d()->functionStructure); - markIfNeeded(markStack, d()->numberObjectStructure); - markIfNeeded(markStack, d()->regExpMatchesArrayStructure); - markIfNeeded(markStack, d()->regExpStructure); - markIfNeeded(markStack, d()->stringObjectStructure); - - // No need to mark the other structures, because their prototypes are all - // guaranteed to be referenced elsewhere. - - if (d()->registerArray) { + + markIfNeeded(markStack, &m_globalScopeChain); + markIfNeeded(markStack, &m_methodCallDummy); + + markIfNeeded(markStack, &m_regExpConstructor); + markIfNeeded(markStack, &m_errorConstructor); + markIfNeeded(markStack, &m_evalErrorConstructor); + markIfNeeded(markStack, &m_rangeErrorConstructor); + markIfNeeded(markStack, &m_referenceErrorConstructor); + markIfNeeded(markStack, &m_syntaxErrorConstructor); + markIfNeeded(markStack, &m_typeErrorConstructor); + markIfNeeded(markStack, &m_URIErrorConstructor); + + markIfNeeded(markStack, &m_evalFunction); + markIfNeeded(markStack, &m_callFunction); + markIfNeeded(markStack, &m_applyFunction); + + markIfNeeded(markStack, &m_objectPrototype); + markIfNeeded(markStack, &m_functionPrototype); + markIfNeeded(markStack, &m_arrayPrototype); + markIfNeeded(markStack, &m_booleanPrototype); + markIfNeeded(markStack, &m_stringPrototype); + markIfNeeded(markStack, &m_numberPrototype); + markIfNeeded(markStack, &m_datePrototype); + markIfNeeded(markStack, &m_regExpPrototype); + + markIfNeeded(markStack, m_argumentsStructure); + markIfNeeded(markStack, m_arrayStructure); + markIfNeeded(markStack, m_booleanObjectStructure); + markIfNeeded(markStack, m_callbackConstructorStructure); + markIfNeeded(markStack, m_callbackFunctionStructure); + markIfNeeded(markStack, m_callbackObjectStructure); + markIfNeeded(markStack, m_dateStructure); + markIfNeeded(markStack, m_emptyObjectStructure); + markIfNeeded(markStack, m_errorStructure); + markIfNeeded(markStack, m_functionStructure); + markIfNeeded(markStack, m_numberObjectStructure); + markIfNeeded(markStack, m_regExpMatchesArrayStructure); + markIfNeeded(markStack, m_regExpStructure); + markIfNeeded(markStack, m_stringObjectStructure); + markIfNeeded(markStack, m_internalFunctionStructure); + + if (m_registerArray) { // Outside the execution of global code, when our variables are torn off, // we can mark the torn-off array. - markStack.appendValues(d()->registerArray.get(), d()->registerArraySize); - } else if (d()->registers) { + markStack.appendValues(m_registerArray.get(), m_registerArraySize); + } else if (m_registers) { // During execution of global code, when our variables are in the register file, // the symbol table tells us how many variables there are, and registers // points to where they end, and the registers used for execution begin. - markStack.appendValues(d()->registers - symbolTable().size(), symbolTable().size()); + markStack.appendValues(m_registers - symbolTable().size(), symbolTable().size()); } } ExecState* JSGlobalObject::globalExec() { - return CallFrame::create(d()->globalCallFrame + RegisterFile::CallFrameHeaderSize); + return CallFrame::create(m_globalCallFrame + RegisterFile::CallFrameHeaderSize); } bool JSGlobalObject::isDynamicScope(bool&) const @@ -388,12 +384,12 @@ bool JSGlobalObject::isDynamicScope(bool&) const void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile) { - ASSERT(!d()->registerArray); - ASSERT(!d()->registerArraySize); + ASSERT(!m_registerArray); + ASSERT(!m_registerArraySize); int numGlobals = registerFile.numGlobals(); if (!numGlobals) { - d()->registers = 0; + m_registers = 0; return; } @@ -411,24 +407,24 @@ void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile) registerFile.setGlobalObject(this); registerFile.setNumGlobals(symbolTable().size()); - if (d()->registerArray) { + if (m_registerArray) { // The register file is always a gc root so no barrier is needed here - memcpy(registerFile.start() - d()->registerArraySize, d()->registerArray.get(), d()->registerArraySize * sizeof(WriteBarrier<Unknown>)); + memcpy(registerFile.start() - m_registerArraySize, m_registerArray.get(), m_registerArraySize * sizeof(WriteBarrier<Unknown>)); setRegisters(reinterpret_cast<WriteBarrier<Unknown>*>(registerFile.start()), nullptr, 0); } } void JSGlobalObject::resizeRegisters(int oldSize, int newSize) { - ASSERT(symbolTable().size() == newSize); + ASSERT(oldSize <= newSize); if (newSize == oldSize) return; ASSERT(newSize && newSize > oldSize); - if (d()->registerArray || !d()->registers) { - ASSERT(static_cast<size_t>(oldSize) == d()->registerArraySize); + if (m_registerArray || !m_registers) { + ASSERT(static_cast<size_t>(oldSize) == m_registerArraySize); OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[newSize]); for (int i = 0; i < oldSize; i++) - registerArray[newSize - oldSize + i].set(globalData(), this, d()->registerArray[i].get()); + registerArray[newSize - oldSize + i].set(globalData(), this, m_registerArray[i].get()); WriteBarrier<Unknown>* registers = registerArray.get() + newSize; setRegisters(registers, registerArray.release(), newSize); } else { @@ -437,7 +433,7 @@ void JSGlobalObject::resizeRegisters(int oldSize, int newSize) } for (int i = -newSize; i < -oldSize; ++i) - d()->registers[i].setUndefined(); + m_registers[i].setUndefined(); } void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData) @@ -445,26 +441,21 @@ void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData) return globalData->heap.allocate(size); } -void JSGlobalObject::destroyJSGlobalObjectData(void* jsGlobalObjectData) -{ - delete static_cast<JSGlobalObjectData*>(jsGlobalObjectData); -} - -DynamicGlobalObjectScope::DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject) - : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject) +DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSGlobalObject* dynamicGlobalObject) + : m_dynamicGlobalObjectSlot(globalData.dynamicGlobalObject) , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot) { if (!m_dynamicGlobalObjectSlot) { #if ENABLE(ASSEMBLER) if (ExecutableAllocator::underMemoryPressure()) - callFrame->globalData().recompileAllJSFunctions(); + globalData.recompileAllJSFunctions(); #endif m_dynamicGlobalObjectSlot = dynamicGlobalObject; // Reset the date cache between JS invocations to force the VM // to observe time zone changes. - callFrame->globalData().resetDateCache(); + globalData.resetDateCache(); } } diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h index 03b39fc..04f63eb 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.h +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h @@ -28,6 +28,7 @@ #include "JSWeakObjectMapRefInternal.h" #include "NumberPrototype.h" #include "StringPrototype.h" +#include "StructureChain.h" #include <wtf/HashSet.h> #include <wtf/OwnPtr.h> #include <wtf/RandomNumber.h> @@ -54,92 +55,70 @@ namespace JSC { class JSGlobalObject : public JSVariableObject { protected: - using JSVariableObject::JSVariableObjectData; typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet; - struct JSGlobalObjectData : public JSVariableObjectData { - // We use an explicit destructor function pointer instead of a - // virtual destructor because we want to avoid adding a vtable - // pointer to this struct. Adding a vtable pointer would force the - // compiler to emit costly pointer fixup code when casting from - // JSVariableObjectData* to JSGlobalObjectData*. - typedef void (*Destructor)(void*); - - JSGlobalObjectData(Destructor destructor) - : JSVariableObjectData(&symbolTable, 0) - , destructor(destructor) - , registerArraySize(0) - , globalScopeChain() - , weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) - { - } - - Destructor destructor; - - size_t registerArraySize; - - JSGlobalObject* next; - JSGlobalObject* prev; - - Debugger* debugger; - - WriteBarrier<ScopeChainNode> globalScopeChain; - Register globalCallFrame[RegisterFile::CallFrameHeaderSize]; - - WriteBarrier<RegExpConstructor> regExpConstructor; - WriteBarrier<ErrorConstructor> errorConstructor; - WriteBarrier<NativeErrorConstructor> evalErrorConstructor; - WriteBarrier<NativeErrorConstructor> rangeErrorConstructor; - WriteBarrier<NativeErrorConstructor> referenceErrorConstructor; - WriteBarrier<NativeErrorConstructor> syntaxErrorConstructor; - WriteBarrier<NativeErrorConstructor> typeErrorConstructor; - WriteBarrier<NativeErrorConstructor> URIErrorConstructor; - - WriteBarrier<JSFunction> evalFunction; - WriteBarrier<JSFunction> callFunction; - WriteBarrier<JSFunction> applyFunction; - - WriteBarrier<ObjectPrototype> objectPrototype; - WriteBarrier<FunctionPrototype> functionPrototype; - WriteBarrier<ArrayPrototype> arrayPrototype; - WriteBarrier<BooleanPrototype> booleanPrototype; - WriteBarrier<StringPrototype> stringPrototype; - WriteBarrier<NumberPrototype> numberPrototype; - WriteBarrier<DatePrototype> datePrototype; - WriteBarrier<RegExpPrototype> regExpPrototype; - - WriteBarrier<JSObject> methodCallDummy; - - RefPtr<Structure> argumentsStructure; - RefPtr<Structure> arrayStructure; - RefPtr<Structure> booleanObjectStructure; - RefPtr<Structure> callbackConstructorStructure; - RefPtr<Structure> callbackFunctionStructure; - RefPtr<Structure> callbackObjectStructure; - RefPtr<Structure> dateStructure; - RefPtr<Structure> emptyObjectStructure; - RefPtr<Structure> errorStructure; - RefPtr<Structure> functionStructure; - RefPtr<Structure> numberObjectStructure; - RefPtr<Structure> regExpMatchesArrayStructure; - RefPtr<Structure> regExpStructure; - RefPtr<Structure> stringObjectStructure; - RefPtr<Structure> internalFunctionStructure; - - SymbolTable symbolTable; - unsigned profileGroup; - - RefPtr<JSGlobalData> globalData; - - WeakMapSet weakMaps; - WeakRandom weakRandom; - }; + RefPtr<JSGlobalData> m_globalData; + + size_t m_registerArraySize; + Register m_globalCallFrame[RegisterFile::CallFrameHeaderSize]; + + WriteBarrier<ScopeChainNode> m_globalScopeChain; + WriteBarrier<JSObject> m_methodCallDummy; + + WriteBarrier<RegExpConstructor> m_regExpConstructor; + WriteBarrier<ErrorConstructor> m_errorConstructor; + WriteBarrier<NativeErrorConstructor> m_evalErrorConstructor; + WriteBarrier<NativeErrorConstructor> m_rangeErrorConstructor; + WriteBarrier<NativeErrorConstructor> m_referenceErrorConstructor; + WriteBarrier<NativeErrorConstructor> m_syntaxErrorConstructor; + WriteBarrier<NativeErrorConstructor> m_typeErrorConstructor; + WriteBarrier<NativeErrorConstructor> m_URIErrorConstructor; + + WriteBarrier<JSFunction> m_evalFunction; + WriteBarrier<JSFunction> m_callFunction; + WriteBarrier<JSFunction> m_applyFunction; + + WriteBarrier<ObjectPrototype> m_objectPrototype; + WriteBarrier<FunctionPrototype> m_functionPrototype; + WriteBarrier<ArrayPrototype> m_arrayPrototype; + WriteBarrier<BooleanPrototype> m_booleanPrototype; + WriteBarrier<StringPrototype> m_stringPrototype; + WriteBarrier<NumberPrototype> m_numberPrototype; + WriteBarrier<DatePrototype> m_datePrototype; + WriteBarrier<RegExpPrototype> m_regExpPrototype; + + RefPtr<Structure> m_argumentsStructure; + RefPtr<Structure> m_arrayStructure; + RefPtr<Structure> m_booleanObjectStructure; + RefPtr<Structure> m_callbackConstructorStructure; + RefPtr<Structure> m_callbackFunctionStructure; + RefPtr<Structure> m_callbackObjectStructure; + RefPtr<Structure> m_dateStructure; + RefPtr<Structure> m_emptyObjectStructure; + RefPtr<Structure> m_errorStructure; + RefPtr<Structure> m_functionStructure; + RefPtr<Structure> m_numberObjectStructure; + RefPtr<Structure> m_regExpMatchesArrayStructure; + RefPtr<Structure> m_regExpStructure; + RefPtr<Structure> m_stringObjectStructure; + RefPtr<Structure> m_internalFunctionStructure; + + unsigned m_profileGroup; + Debugger* m_debugger; + + WeakMapSet m_weakMaps; + WeakRandom m_weakRandom; + + SymbolTable m_symbolTable; public: void* operator new(size_t, JSGlobalData*); - explicit JSGlobalObject() - : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData(destroyJSGlobalObjectData)) + explicit JSGlobalObject(JSGlobalData& globalData) + : JSVariableObject(JSGlobalObject::createStructure(globalData, jsNull()), &m_symbolTable, 0) + , m_registerArraySize(0) + , m_globalScopeChain() + , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) { COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot); putThisToAnonymousValue(0); @@ -147,7 +126,10 @@ namespace JSC { } explicit JSGlobalObject(NonNullPassRefPtr<Structure> structure) - : JSVariableObject(structure, new JSGlobalObjectData(destroyJSGlobalObjectData)) + : JSVariableObject(structure, &m_symbolTable, 0) + , m_registerArraySize(0) + , m_globalScopeChain() + , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) { COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot); putThisToAnonymousValue(0); @@ -155,8 +137,11 @@ namespace JSC { } protected: - JSGlobalObject(NonNullPassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue) - : JSVariableObject(structure, data) + JSGlobalObject(NonNullPassRefPtr<Structure> structure, JSObject* thisValue) + : JSVariableObject(structure, &m_symbolTable, 0) + , m_registerArraySize(0) + , m_globalScopeChain() + , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) { COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot); putThisToAnonymousValue(0); @@ -184,55 +169,57 @@ namespace JSC { // The following accessors return pristine values, even if a script // replaces the global object's associated property. - RegExpConstructor* regExpConstructor() const { return d()->regExpConstructor.get(); } - - ErrorConstructor* errorConstructor() const { return d()->errorConstructor.get(); } - NativeErrorConstructor* evalErrorConstructor() const { return d()->evalErrorConstructor.get(); } - NativeErrorConstructor* rangeErrorConstructor() const { return d()->rangeErrorConstructor.get(); } - NativeErrorConstructor* referenceErrorConstructor() const { return d()->referenceErrorConstructor.get(); } - NativeErrorConstructor* syntaxErrorConstructor() const { return d()->syntaxErrorConstructor.get(); } - NativeErrorConstructor* typeErrorConstructor() const { return d()->typeErrorConstructor.get(); } - NativeErrorConstructor* URIErrorConstructor() const { return d()->URIErrorConstructor.get(); } - - JSFunction* evalFunction() const { return d()->evalFunction.get(); } - - ObjectPrototype* objectPrototype() const { return d()->objectPrototype.get(); } - FunctionPrototype* functionPrototype() const { return d()->functionPrototype.get(); } - ArrayPrototype* arrayPrototype() const { return d()->arrayPrototype.get(); } - BooleanPrototype* booleanPrototype() const { return d()->booleanPrototype.get(); } - StringPrototype* stringPrototype() const { return d()->stringPrototype.get(); } - NumberPrototype* numberPrototype() const { return d()->numberPrototype.get(); } - DatePrototype* datePrototype() const { return d()->datePrototype.get(); } - RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype.get(); } - - JSObject* methodCallDummy() const { return d()->methodCallDummy.get(); } - - Structure* argumentsStructure() const { return d()->argumentsStructure.get(); } - Structure* arrayStructure() const { return d()->arrayStructure.get(); } - Structure* booleanObjectStructure() const { return d()->booleanObjectStructure.get(); } - Structure* callbackConstructorStructure() const { return d()->callbackConstructorStructure.get(); } - Structure* callbackFunctionStructure() const { return d()->callbackFunctionStructure.get(); } - Structure* callbackObjectStructure() const { return d()->callbackObjectStructure.get(); } - Structure* dateStructure() const { return d()->dateStructure.get(); } - Structure* emptyObjectStructure() const { return d()->emptyObjectStructure.get(); } - Structure* errorStructure() const { return d()->errorStructure.get(); } - Structure* functionStructure() const { return d()->functionStructure.get(); } - Structure* numberObjectStructure() const { return d()->numberObjectStructure.get(); } - Structure* internalFunctionStructure() const { return d()->internalFunctionStructure.get(); } - Structure* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); } - Structure* regExpStructure() const { return d()->regExpStructure.get(); } - Structure* stringObjectStructure() const { return d()->stringObjectStructure.get(); } - - void setProfileGroup(unsigned value) { d()->profileGroup = value; } - unsigned profileGroup() const { return d()->profileGroup; } - - Debugger* debugger() const { return d()->debugger; } - void setDebugger(Debugger* debugger) { d()->debugger = debugger; } + RegExpConstructor* regExpConstructor() const { return m_regExpConstructor.get(); } + + ErrorConstructor* errorConstructor() const { return m_errorConstructor.get(); } + NativeErrorConstructor* evalErrorConstructor() const { return m_evalErrorConstructor.get(); } + NativeErrorConstructor* rangeErrorConstructor() const { return m_rangeErrorConstructor.get(); } + NativeErrorConstructor* referenceErrorConstructor() const { return m_referenceErrorConstructor.get(); } + NativeErrorConstructor* syntaxErrorConstructor() const { return m_syntaxErrorConstructor.get(); } + NativeErrorConstructor* typeErrorConstructor() const { return m_typeErrorConstructor.get(); } + NativeErrorConstructor* URIErrorConstructor() const { return m_URIErrorConstructor.get(); } + + JSFunction* evalFunction() const { return m_evalFunction.get(); } + JSFunction* callFunction() const { return m_callFunction.get(); } + JSFunction* applyFunction() const { return m_applyFunction.get(); } + + ObjectPrototype* objectPrototype() const { return m_objectPrototype.get(); } + FunctionPrototype* functionPrototype() const { return m_functionPrototype.get(); } + ArrayPrototype* arrayPrototype() const { return m_arrayPrototype.get(); } + BooleanPrototype* booleanPrototype() const { return m_booleanPrototype.get(); } + StringPrototype* stringPrototype() const { return m_stringPrototype.get(); } + NumberPrototype* numberPrototype() const { return m_numberPrototype.get(); } + DatePrototype* datePrototype() const { return m_datePrototype.get(); } + RegExpPrototype* regExpPrototype() const { return m_regExpPrototype.get(); } + + JSObject* methodCallDummy() const { return m_methodCallDummy.get(); } + + Structure* argumentsStructure() const { return m_argumentsStructure.get(); } + Structure* arrayStructure() const { return m_arrayStructure.get(); } + Structure* booleanObjectStructure() const { return m_booleanObjectStructure.get(); } + Structure* callbackConstructorStructure() const { return m_callbackConstructorStructure.get(); } + Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(); } + Structure* callbackObjectStructure() const { return m_callbackObjectStructure.get(); } + Structure* dateStructure() const { return m_dateStructure.get(); } + Structure* emptyObjectStructure() const { return m_emptyObjectStructure.get(); } + Structure* errorStructure() const { return m_errorStructure.get(); } + Structure* functionStructure() const { return m_functionStructure.get(); } + Structure* numberObjectStructure() const { return m_numberObjectStructure.get(); } + Structure* internalFunctionStructure() const { return m_internalFunctionStructure.get(); } + Structure* regExpMatchesArrayStructure() const { return m_regExpMatchesArrayStructure.get(); } + Structure* regExpStructure() const { return m_regExpStructure.get(); } + Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); } + + void setProfileGroup(unsigned value) { m_profileGroup = value; } + unsigned profileGroup() const { return m_profileGroup; } + + Debugger* debugger() const { return m_debugger; } + void setDebugger(Debugger* debugger) { m_debugger = debugger; } virtual bool supportsProfiling() const { return false; } virtual bool supportsRichSourceInfo() const { return true; } - ScopeChainNode* globalScopeChain() { return d()->globalScopeChain.get(); } + ScopeChainNode* globalScopeChain() { return m_globalScopeChain.get(); } virtual bool isGlobalObject() const { return true; } @@ -250,25 +237,24 @@ namespace JSC { void resetPrototype(JSValue prototype); - JSGlobalData& globalData() const { return *d()->globalData.get(); } - JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); } + JSGlobalData& globalData() const { return *m_globalData.get(); } - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } void registerWeakMap(OpaqueJSWeakObjectMap* map) { - d()->weakMaps.add(map); + m_weakMaps.add(map); } void deregisterWeakMap(OpaqueJSWeakObjectMap* map) { - d()->weakMaps.remove(map); + m_weakMaps.remove(map); } - double weakRandomNumber() { return d()->weakRandom.get(); } + double weakRandomNumber() { return m_weakRandom.get(); } protected: static const unsigned AnonymousSlotCount = JSVariableObject::AnonymousSlotCount + 1; @@ -289,8 +275,6 @@ namespace JSC { void addStaticGlobals(GlobalPropertyInfo*, int count); private: - static void destroyJSGlobalObjectData(void*); - // FIXME: Fold reset into init. void init(JSObject* thisValue); void reset(JSValue prototype); @@ -311,17 +295,17 @@ namespace JSC { inline void JSGlobalObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count) { JSVariableObject::setRegisters(registers, registerArray); - d()->registerArraySize = count; + m_registerArraySize = count; } inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count) { - size_t oldSize = d()->registerArraySize; + size_t oldSize = m_registerArraySize; size_t newSize = oldSize + count; OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[newSize]); - if (d()->registerArray) { + if (m_registerArray) { // memcpy is safe here as we're copying barriers we already own from the existing array - memcpy(registerArray.get() + count, d()->registerArray.get(), oldSize * sizeof(Register)); + memcpy(registerArray.get() + count, m_registerArray.get(), oldSize * sizeof(Register)); } WriteBarrier<Unknown>* registers = registerArray.get() + newSize; @@ -379,7 +363,7 @@ namespace JSC { // We cache our prototype chain so our clients can share it. if (!isValid(exec, m_cachedPrototypeChain.get())) { JSValue prototype = prototypeForLookup(exec); - m_cachedPrototypeChain = StructureChain::create(prototype.isNull() ? 0 : asObject(prototype)->structure()); + m_cachedPrototypeChain = StructureChain::create(exec->globalData(), prototype.isNull() ? 0 : asObject(prototype)->structure()); } return m_cachedPrototypeChain.get(); } @@ -451,7 +435,7 @@ namespace JSC { class DynamicGlobalObjectScope { WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope); public: - DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject); + DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*); ~DynamicGlobalObjectScope() { diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index de1300a..f0da773 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -449,12 +449,12 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec) if (JSValue parsedObject = preparser.tryLiteralParse()) return JSValue::encode(parsedObject); - RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s), false); + EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false); JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain()); if (error) return throwVMError(exec, error); - return JSValue::encode(exec->interpreter()->execute(eval.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain())); + return JSValue::encode(exec->interpreter()->execute(eval, exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain())); } EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/JSLock.cpp b/Source/JavaScriptCore/runtime/JSLock.cpp index 64dcb08..fc543f0 100644 --- a/Source/JavaScriptCore/runtime/JSLock.cpp +++ b/Source/JavaScriptCore/runtime/JSLock.cpp @@ -23,6 +23,7 @@ #include "Heap.h" #include "CallFrame.h" +#include "JSObject.h" #include "ScopeChain.h" #if USE(PTHREADS) diff --git a/Source/JavaScriptCore/runtime/JSNotAnObject.cpp b/Source/JavaScriptCore/runtime/JSNotAnObject.cpp index e01b401..1115dc0 100644 --- a/Source/JavaScriptCore/runtime/JSNotAnObject.cpp +++ b/Source/JavaScriptCore/runtime/JSNotAnObject.cpp @@ -67,7 +67,7 @@ UString JSNotAnObject::toString(ExecState* exec) const return ""; } -JSObject* JSNotAnObject::toObject(ExecState* exec) const +JSObject* JSNotAnObject::toObject(ExecState* exec, JSGlobalObject*) const { ASSERT_UNUSED(exec, exec->hadException()); return const_cast<JSNotAnObject*>(this); diff --git a/Source/JavaScriptCore/runtime/JSNotAnObject.h b/Source/JavaScriptCore/runtime/JSNotAnObject.h index 7e70a98..75bca18 100644 --- a/Source/JavaScriptCore/runtime/JSNotAnObject.h +++ b/Source/JavaScriptCore/runtime/JSNotAnObject.h @@ -43,9 +43,9 @@ namespace JSC { { } - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } private: @@ -58,7 +58,7 @@ namespace JSC { virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; - virtual JSObject* toObject(ExecState*) const; + virtual JSObject* toObject(ExecState*, JSGlobalObject*) const; // JSObject methods virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); diff --git a/Source/JavaScriptCore/runtime/JSNumberCell.cpp b/Source/JavaScriptCore/runtime/JSNumberCell.cpp index 3172cc9..79f2d2a 100644 --- a/Source/JavaScriptCore/runtime/JSNumberCell.cpp +++ b/Source/JavaScriptCore/runtime/JSNumberCell.cpp @@ -22,6 +22,7 @@ #include "config.h" #include "JSNumberCell.h" +#include "JSObject.h" #include "ScopeChain.h" // Keep our exported symbols lists happy. diff --git a/Source/JavaScriptCore/runtime/JSONObject.cpp b/Source/JavaScriptCore/runtime/JSONObject.cpp index 7d18e08..8fc7ac9 100644 --- a/Source/JavaScriptCore/runtime/JSONObject.cpp +++ b/Source/JavaScriptCore/runtime/JSONObject.cpp @@ -32,6 +32,8 @@ #include "JSArray.h" #include "JSGlobalObject.h" #include "LiteralParser.h" +#include "Local.h" +#include "LocalScope.h" #include "Lookup.h" #include "PropertyNameArray.h" #include "UStringBuilder.h" @@ -74,24 +76,22 @@ private: class Stringifier { WTF_MAKE_NONCOPYABLE(Stringifier); public: - Stringifier(ExecState*, JSValue replacer, JSValue space); - ~Stringifier(); - JSValue stringify(JSValue); + Stringifier(ExecState*, const Local<Unknown>& replacer, const Local<Unknown>& space); + Local<Unknown> stringify(Handle<Unknown>); void markAggregate(MarkStack&); private: class Holder { public: - Holder(JSObject*); + Holder(JSGlobalData&, JSObject*); JSObject* object() const { return m_object.get(); } - DeprecatedPtr<JSObject>* objectSlot() { return &m_object; } bool appendNextProperty(Stringifier&, UStringBuilder&); private: - DeprecatedPtr<JSObject> m_object; + Local<JSObject> m_object; const bool m_isArray; bool m_isJSArray; unsigned m_index; @@ -113,16 +113,14 @@ private: void unindent(); void startNewLine(UStringBuilder&) const; - Stringifier* const m_nextStringifierToMark; ExecState* const m_exec; - const JSValue m_replacer; + const Local<Unknown> m_replacer; bool m_usingArrayReplacer; PropertyNameArray m_arrayReplacerPropertyNames; CallType m_replacerCallType; CallData m_replacerCallData; const UString m_gap; - HashSet<JSObject*> m_holderCycleDetector; Vector<Holder, 16> m_holderStack; UString m_repeatedGap; UString m_indent; @@ -199,23 +197,20 @@ JSValue PropertyNameForFunctionCall::value(ExecState* exec) const // ------------------------------ Stringifier -------------------------------- -Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space) - : m_nextStringifierToMark(exec->globalData().firstStringifierToMark) - , m_exec(exec) +Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const Local<Unknown>& space) + : m_exec(exec) , m_replacer(replacer) , m_usingArrayReplacer(false) , m_arrayReplacerPropertyNames(exec) , m_replacerCallType(CallTypeNone) - , m_gap(gap(exec, space)) + , m_gap(gap(exec, space.get())) { - exec->globalData().firstStringifierToMark = this; - if (!m_replacer.isObject()) return; - if (asObject(m_replacer)->inherits(&JSArray::s_info)) { + if (m_replacer.asObject()->inherits(&JSArray::s_info)) { m_usingArrayReplacer = true; - JSObject* array = asObject(m_replacer); + Handle<JSObject> array = m_replacer.asObject(); unsigned length = array->get(exec, exec->globalData().propertyNames->length).toUInt32(exec); for (unsigned i = 0; i < length; ++i) { JSValue name = array->get(exec, i); @@ -246,40 +241,25 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space) return; } - m_replacerCallType = asObject(m_replacer)->getCallData(m_replacerCallData); -} - -Stringifier::~Stringifier() -{ - ASSERT(m_exec->globalData().firstStringifierToMark == this); - m_exec->globalData().firstStringifierToMark = m_nextStringifierToMark; -} - -void Stringifier::markAggregate(MarkStack& markStack) -{ - for (Stringifier* stringifier = this; stringifier; stringifier = stringifier->m_nextStringifierToMark) { - size_t size = m_holderStack.size(); - for (size_t i = 0; i < size; ++i) - markStack.append(m_holderStack[i].objectSlot()); - } + m_replacerCallType = m_replacer.asObject()->getCallData(m_replacerCallData); } -JSValue Stringifier::stringify(JSValue value) +Local<Unknown> Stringifier::stringify(Handle<Unknown> value) { JSObject* object = constructEmptyObject(m_exec); if (m_exec->hadException()) - return jsNull(); + return Local<Unknown>(m_exec->globalData(), jsNull()); PropertyNameForFunctionCall emptyPropertyName(m_exec->globalData().propertyNames->emptyIdentifier); - object->putDirect(m_exec->globalData(), m_exec->globalData().propertyNames->emptyIdentifier, value); + object->putDirect(m_exec->globalData(), m_exec->globalData().propertyNames->emptyIdentifier, value.get()); UStringBuilder result; - if (appendStringifiedValue(result, value, object, emptyPropertyName) != StringifySucceeded) - return jsUndefined(); + if (appendStringifiedValue(result, value.get(), object, emptyPropertyName) != StringifySucceeded) + return Local<Unknown>(m_exec->globalData(), jsUndefined()); if (m_exec->hadException()) - return jsNull(); + return Local<Unknown>(m_exec->globalData(), jsNull()); - return jsString(m_exec, result.toUString()); + return Local<Unknown>(m_exec->globalData(), jsString(m_exec, result.toUString())); } void Stringifier::appendQuotedString(UStringBuilder& builder, const UString& value) @@ -372,7 +352,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder& if (m_replacerCallType != CallTypeNone) { JSValue list[] = { propertyName.value(m_exec), value }; ArgList args(list, WTF_ARRAY_LENGTH(list)); - value = call(m_exec, m_replacer, m_replacerCallType, m_replacerCallData, holder, args); + value = call(m_exec, m_replacer.get(), m_replacerCallType, m_replacerCallData, holder, args); if (m_exec->hadException()) return StringifyFailed; } @@ -425,12 +405,14 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder& } // Handle cycle detection, and put the holder on the stack. - if (!m_holderCycleDetector.add(object).second) { - throwError(m_exec, createTypeError(m_exec, "JSON.stringify cannot serialize cyclic structures.")); - return StringifyFailed; + for (unsigned i = 0; i < m_holderStack.size(); i++) { + if (m_holderStack[i].object() == object) { + throwError(m_exec, createTypeError(m_exec, "JSON.stringify cannot serialize cyclic structures.")); + return StringifyFailed; + } } bool holderStackWasEmpty = m_holderStack.isEmpty(); - m_holderStack.append(object); + m_holderStack.append(Holder(m_exec->globalData(), object)); if (!holderStackWasEmpty) return StringifySucceeded; @@ -450,7 +432,6 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder& tickCount = localTimeoutChecker.ticksUntilNextCheck(); } } - m_holderCycleDetector.remove(m_holderStack.last().object()); m_holderStack.removeLast(); } while (!m_holderStack.isEmpty()); return StringifySucceeded; @@ -485,8 +466,8 @@ inline void Stringifier::startNewLine(UStringBuilder& builder) const builder.append(m_indent); } -inline Stringifier::Holder::Holder(JSObject* object) - : m_object(object) +inline Stringifier::Holder::Holder(JSGlobalData& globalData, JSObject* object) + : m_object(globalData, object) , m_isArray(object->inherits(&JSArray::s_info)) , m_index(0) { @@ -623,16 +604,11 @@ bool JSONObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& pro return getStaticFunctionDescriptor<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, descriptor); } -void JSONObject::markStringifiers(MarkStack& markStack, Stringifier* stringifier) -{ - stringifier->markAggregate(markStack); -} - class Walker { public: - Walker(ExecState* exec, JSObject* function, CallType callType, CallData callData) + Walker(ExecState* exec, Handle<JSObject> function, CallType callType, CallData callData) : m_exec(exec) - , m_function(function) + , m_function(exec->globalData(), function) , m_callType(callType) , m_callData(callData) { @@ -649,7 +625,7 @@ private: friend class Holder; ExecState* m_exec; - DeprecatedPtr<JSObject> m_function; + Local<JSObject> m_function; CallType m_callType; CallData m_callData; }; @@ -663,8 +639,8 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) { Vector<PropertyNameArray, 16> propertyStack; Vector<uint32_t, 16> indexStack; - Vector<JSObject*, 16> objectStack; - Vector<JSArray*, 16> arrayStack; + LocalStack<JSObject, 16> objectStack(m_exec->globalData()); + LocalStack<JSArray, 16> arrayStack(m_exec->globalData()); Vector<WalkerState, 16> stateStack; WalkerState state = StateUnknown; @@ -684,7 +660,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) return throwError(m_exec, createStackOverflowError(m_exec)); JSArray* array = asArray(inValue); - arrayStack.append(array); + arrayStack.push(array); indexStack.append(0); // fallthrough } @@ -696,11 +672,11 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) tickCount = localTimeoutChecker.ticksUntilNextCheck(); } - JSArray* array = arrayStack.last(); + JSArray* array = arrayStack.peek(); uint32_t index = indexStack.last(); if (index == array->length()) { outValue = array; - arrayStack.removeLast(); + arrayStack.pop(); indexStack.removeLast(); break; } @@ -722,7 +698,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) // fallthrough } case ArrayEndVisitMember: { - JSArray* array = arrayStack.last(); + JSArray* array = arrayStack.peek(); JSValue filteredValue = callReviver(array, jsString(m_exec, UString::number(indexStack.last())), outValue); if (filteredValue.isUndefined()) array->deleteProperty(m_exec, indexStack.last()); @@ -745,7 +721,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) return throwError(m_exec, createStackOverflowError(m_exec)); JSObject* object = asObject(inValue); - objectStack.append(object); + objectStack.push(object); indexStack.append(0); propertyStack.append(PropertyNameArray(m_exec)); object->getOwnPropertyNames(m_exec, propertyStack.last()); @@ -759,12 +735,12 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) tickCount = localTimeoutChecker.ticksUntilNextCheck(); } - JSObject* object = objectStack.last(); + JSObject* object = objectStack.peek(); uint32_t index = indexStack.last(); PropertyNameArray& properties = propertyStack.last(); if (index == properties.size()) { outValue = object; - objectStack.removeLast(); + objectStack.pop(); indexStack.removeLast(); propertyStack.removeLast(); break; @@ -787,7 +763,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) // fallthrough } case ObjectEndVisitMember: { - JSObject* object = objectStack.last(); + JSObject* object = objectStack.peek(); Identifier prop = propertyStack.last()[indexStack.last()]; PutPropertySlot slot; JSValue filteredValue = callReviver(object, jsString(m_exec, prop.ustring()), outValue); @@ -838,7 +814,8 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec) UString source = value.toString(exec); if (exec->hadException()) return JSValue::encode(jsNull()); - + + LocalScope scope(exec->globalData()); LiteralParser jsonParser(exec, source, LiteralParser::StrictJSON); JSValue unfiltered = jsonParser.tryLiteralParse(); if (!unfiltered) @@ -852,7 +829,7 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec) CallType callType = getCallData(function, callData); if (callType == CallTypeNone) return JSValue::encode(unfiltered); - return JSValue::encode(Walker(exec, asObject(function), callType, callData).walk(unfiltered)); + return JSValue::encode(Walker(exec, Local<JSObject>(exec->globalData(), asObject(function)), callType, callData).walk(unfiltered)); } // ECMA-262 v5 15.12.3 @@ -860,15 +837,17 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState* exec) { if (!exec->argumentCount()) return throwVMError(exec, createError(exec, "No input to stringify")); - JSValue value = exec->argument(0); - JSValue replacer = exec->argument(1); - JSValue space = exec->argument(2); - return JSValue::encode(Stringifier(exec, replacer, space).stringify(value)); + LocalScope scope(exec->globalData()); + Local<Unknown> value(exec->globalData(), exec->argument(0)); + Local<Unknown> replacer(exec->globalData(), exec->argument(1)); + Local<Unknown> space(exec->globalData(), exec->argument(2)); + return JSValue::encode(Stringifier(exec, replacer, space).stringify(value).get()); } UString JSONStringify(ExecState* exec, JSValue value, unsigned indent) { - JSValue result = Stringifier(exec, jsNull(), jsNumber(indent)).stringify(value); + LocalScope scope(exec->globalData()); + Local<Unknown> result = Stringifier(exec, Local<Unknown>(exec->globalData(), jsNull()), Local<Unknown>(exec->globalData(), jsNumber(indent))).stringify(Local<Unknown>(exec->globalData(), value)); if (result.isUndefinedOrNull()) return UString(); return result.getString(exec); diff --git a/Source/JavaScriptCore/runtime/JSONObject.h b/Source/JavaScriptCore/runtime/JSONObject.h index acffeca..a52c543 100644 --- a/Source/JavaScriptCore/runtime/JSONObject.h +++ b/Source/JavaScriptCore/runtime/JSONObject.h @@ -36,13 +36,11 @@ namespace JSC { public: JSONObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure); - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } - static void markStringifiers(MarkStack&, Stringifier*); - protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags; diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index 87fbb67..b307540 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -43,7 +43,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSObject); ASSERT_CLASS_FITS_IN_CELL(JSNonFinalObject); -ASSERT_CLASS_FILLS_CELL(JSFinalObject); +ASSERT_CLASS_FITS_IN_CELL(JSFinalObject); const char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property."; @@ -489,7 +489,7 @@ UString JSObject::toString(ExecState* exec) const return primitive.toString(exec); } -JSObject* JSObject::toObject(ExecState*) const +JSObject* JSObject::toObject(ExecState*, JSGlobalObject*) const { return const_cast<JSObject*>(this); } @@ -572,9 +572,9 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, WriteBarr slot.setUndefined(); } -Structure* JSObject::createInheritorID() +Structure* JSObject::createInheritorID(JSGlobalData& globalData) { - m_inheritorID = createEmptyObjectStructure(this); + m_inheritorID = createEmptyObjectStructure(globalData, this); return m_inheritorID.get(); } @@ -743,12 +743,12 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName // Changing the accessor functions of an existing accessor property ASSERT(descriptor.isAccessorDescriptor()); if (!current.configurable()) { - if (descriptor.setterPresent() && !(current.setter() && JSValue::strictEqual(exec, current.setter(), descriptor.setter()))) { + if (descriptor.setterPresent() && !(current.setterPresent() && JSValue::strictEqual(exec, current.setter(), descriptor.setter()))) { if (throwException) throwError(exec, createTypeError(exec, "Attempting to change the setter of an unconfigurable property.")); return false; } - if (descriptor.getterPresent() && !(current.getter() && JSValue::strictEqual(exec, current.getter(), descriptor.getter()))) { + if (descriptor.getterPresent() && !(current.getterPresent() && JSValue::strictEqual(exec, current.getter(), descriptor.getter()))) { if (throwException) throwError(exec, createTypeError(exec, "Attempting to change the getter of an unconfigurable property.")); return false; diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index 2b4db43..578b3cf 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -92,7 +92,7 @@ namespace JSC { bool setPrototypeWithCycleCheck(JSValue prototype); void setStructure(NonNullPassRefPtr<Structure>); - Structure* inheritorID(); + Structure* inheritorID(JSGlobalData&); virtual UString className() const; @@ -138,7 +138,7 @@ namespace JSC { virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; - virtual JSObject* toObject(ExecState*) const; + virtual JSObject* toObject(ExecState*, JSGlobalObject*) const; virtual JSObject* toThisObject(ExecState*) const; virtual JSValue toStrictThisObject(ExecState*) const; @@ -250,9 +250,9 @@ namespace JSC { static JS_EXPORTDATA const ClassInfo s_info; protected: - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static const unsigned StructureFlags = 0; @@ -296,7 +296,7 @@ namespace JSC { bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const; - Structure* createInheritorID(); + Structure* createInheritorID(JSGlobalData&); PropertyStorage m_propertyStorage; RefPtr<Structure> m_inheritorID; @@ -320,9 +320,9 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt friend class JSObject; public: - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: @@ -348,9 +348,9 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt return new (exec) JSFinalObject(structure); } - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } private: @@ -377,9 +377,9 @@ inline JSObject* constructEmptyObject(ExecState* exec, NonNullPassRefPtr<Structu return JSFinalObject::create(exec, structure); } -inline PassRefPtr<Structure> createEmptyObjectStructure(JSValue prototype) +inline PassRefPtr<Structure> createEmptyObjectStructure(JSGlobalData& globalData, JSValue prototype) { - return JSFinalObject::createStructure(prototype); + return JSFinalObject::createStructure(globalData, prototype); } inline JSObject* asObject(JSCell* cell) @@ -442,11 +442,11 @@ inline void JSObject::setStructure(NonNullPassRefPtr<Structure> structure) m_structure = structure.leakRef(); // ~JSObject balances this ref() } -inline Structure* JSObject::inheritorID() +inline Structure* JSObject::inheritorID(JSGlobalData& globalData) { if (m_inheritorID) return m_inheritorID.get(); - return createInheritorID(); + return createInheritorID(globalData); } inline bool Structure::isUsingInlineStorage() const @@ -814,8 +814,10 @@ inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value) ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack) { JSCell::markChildren(markStack); - + markStack.append(m_structure->storedPrototypeSlot()); + if (*m_structure->cachedPrototypeChainSlot()) + markStack.append(m_structure->cachedPrototypeChainSlot()); PropertyStorage storage = propertyStorage(); size_t storageSize = m_structure->propertyStorageSize(); markStack.appendValues(storage, storageSize); @@ -840,6 +842,20 @@ inline JSValue JSValue::toStrictThisObject(ExecState* exec) const return asObject(asCell())->toStrictThisObject(exec); } +ALWAYS_INLINE JSObject* Register::function() const +{ + if (!jsValue()) + return 0; + return asObject(jsValue()); +} + +ALWAYS_INLINE Register Register::withCallee(JSObject* callee) +{ + Register r; + r = JSValue(callee); + return r; +} + } // namespace JSC #endif // JSObject_h diff --git a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h index c5e3047..8380514 100644 --- a/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h +++ b/Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h @@ -34,9 +34,9 @@ class JSGlobalObject; class JSObjectWithGlobalObject : public JSNonFinalObject { public: - static PassRefPtr<Structure> createStructure(JSValue proto) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } JSGlobalObject* globalObject() const; diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp index 0d759cf..6f31f99 100644 --- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp +++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp @@ -77,7 +77,7 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject return jsPropertyNameIterator; } - jsPropertyNameIterator->setCachedPrototypeChain(structureChain); + jsPropertyNameIterator->setCachedPrototypeChain(exec->globalData(), structureChain); jsPropertyNameIterator->setCachedStructure(o->structure()); o->structure()->setEnumerationCache(exec->globalData(), jsPropertyNameIterator); return jsPropertyNameIterator; @@ -86,7 +86,7 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i) { JSValue identifier = m_jsStrings[i].get(); - if (m_cachedStructure == base->structure() && m_cachedPrototypeChain == base->structure()->prototypeChain(exec)) + if (m_cachedStructure == base->structure() && m_cachedPrototypeChain.get() == base->structure()->prototypeChain(exec)) return identifier; if (!base->hasProperty(exec, Identifier(exec, asString(identifier)->value(exec)))) @@ -97,6 +97,8 @@ JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i) void JSPropertyNameIterator::markChildren(MarkStack& markStack) { markStack.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues); + if (m_cachedPrototypeChain) + markStack.append(&m_cachedPrototypeChain); } #if !ASSERT_DISABLED diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h index d51cba8..499396c 100644 --- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h +++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h @@ -45,9 +45,9 @@ namespace JSC { public: static JSPropertyNameIterator* create(ExecState*, JSObject*); - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren), AnonymousSlotCount, 0); + return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesMarkChildren), AnonymousSlotCount, 0); } virtual bool isPropertyNameIterator() const { return true; } @@ -73,7 +73,7 @@ namespace JSC { } Structure* cachedStructure() { return m_cachedStructure.get(); } - void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; } + void setCachedPrototypeChain(JSGlobalData& globalData, StructureChain* cachedPrototypeChain) { m_cachedPrototypeChain.set(globalData, this, cachedPrototypeChain); } StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); } private: @@ -84,7 +84,7 @@ namespace JSC { #endif RefPtr<Structure> m_cachedStructure; - RefPtr<StructureChain> m_cachedPrototypeChain; + WriteBarrier<StructureChain> m_cachedPrototypeChain; uint32_t m_numCacheableSlots; uint32_t m_jsStringsSize; OwnArrayPtr<WriteBarrier<Unknown> > m_jsStrings; @@ -106,6 +106,11 @@ namespace JSC { return m_enumerationCache.get(); } + ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const + { + return static_cast<JSPropertyNameIterator*>(jsValue().asCell()); + } + } // namespace JSC #endif // JSPropertyNameIterator_h diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp index 727ac28..3d4dc7c 100644 --- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp +++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp @@ -28,13 +28,12 @@ #include "JSStaticScopeObject.h" namespace JSC { - ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject); void JSStaticScopeObject::markChildren(MarkStack& markStack) { JSVariableObject::markChildren(markStack); - markStack.deprecatedAppend(&d()->registerStore); + markStack.append(&m_registerStore); } JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const @@ -68,12 +67,6 @@ bool JSStaticScopeObject::isDynamicScope(bool&) const return false; } -JSStaticScopeObject::~JSStaticScopeObject() -{ - ASSERT(d()); - delete d(); -} - bool JSStaticScopeObject::getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot& slot) { return symbolTableGet(propertyName, slot); diff --git a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h index b3c0695..3e19bbc 100644 --- a/Source/JavaScriptCore/runtime/JSStaticScopeObject.h +++ b/Source/JavaScriptCore/runtime/JSStaticScopeObject.h @@ -31,25 +31,14 @@ namespace JSC{ class JSStaticScopeObject : public JSVariableObject { - protected: - using JSVariableObject::JSVariableObjectData; - struct JSStaticScopeObjectData : public JSVariableObjectData { - JSStaticScopeObjectData() - : JSVariableObjectData(&symbolTable, ®isterStore + 1) - { - } - SymbolTable symbolTable; - Register registerStore; - }; - public: JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValue value, unsigned attributes) - : JSVariableObject(exec->globalData().staticScopeStructure, new JSStaticScopeObjectData()) + : JSVariableObject(exec->globalData().staticScopeStructure, &m_symbolTable, reinterpret_cast<Register*>(&m_registerStore + 1)) { - d()->registerStore = value; + m_registerStore.set(exec->globalData(), this, value); symbolTable().add(ident.impl(), SymbolTableEntry(-1, attributes)); } - virtual ~JSStaticScopeObject(); + virtual void markChildren(MarkStack&); bool isDynamicScope(bool& requiresDynamicChecks) const; virtual JSObject* toThisObject(ExecState*) const; @@ -58,13 +47,14 @@ namespace JSC{ virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes); - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags; private: - JSStaticScopeObjectData* d() { return static_cast<JSStaticScopeObjectData*>(JSVariableObject::d); } + SymbolTable m_symbolTable; + WriteBarrier<Unknown> m_registerStore; }; } diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp index 848c431..d9c4d46 100644 --- a/Source/JavaScriptCore/runtime/JSString.cpp +++ b/Source/JavaScriptCore/runtime/JSString.cpp @@ -152,7 +152,7 @@ JSString* JSString::substringFromRope(ExecState* exec, unsigned substringStart, if (substringLength == 1) { ASSERT(substringFiberCount == 1); UChar c = substringFibers[0].characters()[0]; - if (c <= 0xFF) + if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); } if (substringFiberCount == 1) @@ -253,19 +253,19 @@ UString JSString::toString(ExecState* exec) const return value(exec); } -inline StringObject* StringObject::create(ExecState* exec, JSString* string) +inline StringObject* StringObject::create(ExecState* exec, JSGlobalObject* globalObject, JSString* string) { - return new (exec) StringObject(exec->globalData(), exec->lexicalGlobalObject()->stringObjectStructure(), string); + return new (exec) StringObject(exec->globalData(), globalObject->stringObjectStructure(), string); } -JSObject* JSString::toObject(ExecState* exec) const +JSObject* JSString::toObject(ExecState* exec, JSGlobalObject* globalObject) const { - return StringObject::create(exec, const_cast<JSString*>(this)); + return StringObject::create(exec, globalObject, const_cast<JSString*>(this)); } JSObject* JSString::toThisObject(ExecState* exec) const { - return StringObject::create(exec, const_cast<JSString*>(this)); + return StringObject::create(exec, exec->lexicalGlobalObject(), const_cast<JSString*>(this)); } bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h index 3672300..9113d4a 100644 --- a/Source/JavaScriptCore/runtime/JSString.h +++ b/Source/JavaScriptCore/runtime/JSString.h @@ -349,7 +349,7 @@ namespace JSC { JSValue replaceCharacter(ExecState*, UChar, const UString& replacement); - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount, 0); } + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount, 0); } private: enum VPtrStealingHackType { VPtrStealingHack }; @@ -402,7 +402,7 @@ namespace JSC { virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value); virtual bool toBoolean(ExecState*) const; virtual double toNumber(ExecState*) const; - virtual JSObject* toObject(ExecState*) const; + virtual JSObject* toObject(ExecState*, JSGlobalObject*) const; virtual UString toString(ExecState*) const; virtual JSObject* toThisObject(ExecState*) const; @@ -468,7 +468,7 @@ namespace JSC { inline JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c) { - if (c <= 0xFF) + if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(&c, 1))); } @@ -478,7 +478,7 @@ namespace JSC { JSGlobalData* globalData = &exec->globalData(); ASSERT(offset < static_cast<unsigned>(s.length())); UChar c = s.characters()[offset]; - if (c <= 0xFF) + if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(StringImpl::create(s.impl(), offset, 1)))); } @@ -513,7 +513,7 @@ namespace JSC { return globalData->smallStrings.emptyString(globalData); if (size == 1) { UChar c = s.characters()[0]; - if (c <= 0xFF) + if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); } return fixupVPtr(globalData, new (globalData) JSString(globalData, s)); @@ -521,7 +521,7 @@ namespace JSC { inline JSString* jsStringWithFinalizer(ExecState* exec, const UString& s, JSStringFinalizerCallback callback, void* context) { - ASSERT(s.length() && (s.length() > 1 || s.characters()[0] > 0xFF)); + ASSERT(s.length() && (s.length() > 1 || s.characters()[0] > maxSingleCharacterString)); JSGlobalData* globalData = &exec->globalData(); return fixupVPtr(globalData, new (globalData) JSString(globalData, s, callback, context)); } @@ -548,7 +548,7 @@ namespace JSC { return globalData->smallStrings.emptyString(globalData); if (length == 1) { UChar c = s.characters()[offset]; - if (c <= 0xFF) + if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); } return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(StringImpl::create(s.impl(), offset, length)), JSString::HasOtherOwner)); @@ -561,7 +561,7 @@ namespace JSC { return globalData->smallStrings.emptyString(globalData); if (size == 1) { UChar c = s.characters()[0]; - if (c <= 0xFF) + if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); } return fixupVPtr(globalData, new (globalData) JSString(globalData, s, JSString::HasOtherOwner)); diff --git a/Source/JavaScriptCore/runtime/JSTypeInfo.h b/Source/JavaScriptCore/runtime/JSTypeInfo.h index fdcaf31..284d2b2 100644 --- a/Source/JavaScriptCore/runtime/JSTypeInfo.h +++ b/Source/JavaScriptCore/runtime/JSTypeInfo.h @@ -46,7 +46,6 @@ namespace JSC { static const unsigned IsJSFinalObject = 1 << 8; class TypeInfo { - friend class JIT; public: TypeInfo(JSType type, unsigned flags = 0) : m_type(type) @@ -72,6 +71,16 @@ namespace JSC { unsigned flags() const { return m_flags; } unsigned isFinal() const { return m_flags2 && (IsJSFinalObject >> 8); } + static ptrdiff_t flagsOffset() + { + return OBJECT_OFFSETOF(TypeInfo, m_flags); + } + + static ptrdiff_t typeOffset() + { + return OBJECT_OFFSETOF(TypeInfo, m_type); + } + private: unsigned char m_type; unsigned char m_flags; diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSValue.cpp index f4662db..d3ee89e 100644 --- a/Source/JavaScriptCore/runtime/JSValue.cpp +++ b/Source/JavaScriptCore/runtime/JSValue.cpp @@ -54,14 +54,14 @@ double JSValue::toIntegerPreserveNaN(ExecState* exec) const return trunc(toNumber(exec)); } -JSObject* JSValue::toObjectSlowCase(ExecState* exec) const +JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObject) const { ASSERT(!isCell()); if (isInt32() || isDouble()) - return constructNumber(exec, asValue()); + return constructNumber(exec, globalObject, asValue()); if (isTrue() || isFalse()) - return constructBooleanFromImmediateBoolean(exec, asValue()); + return constructBooleanFromImmediateBoolean(exec, globalObject, asValue()); ASSERT(isUndefinedOrNull()); throwError(exec, createNotAnObjectError(exec, *this)); @@ -73,9 +73,9 @@ JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const ASSERT(!isCell()); if (isInt32() || isDouble()) - return constructNumber(exec, asValue()); + return constructNumber(exec, exec->lexicalGlobalObject(), asValue()); if (isTrue() || isFalse()) - return constructBooleanFromImmediateBoolean(exec, asValue()); + return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue()); ASSERT(isUndefinedOrNull()); return exec->globalThisValue(); } @@ -84,9 +84,9 @@ JSObject* JSValue::synthesizeObject(ExecState* exec) const { ASSERT(!isCell()); if (isNumber()) - return constructNumber(exec, asValue()); + return constructNumber(exec, exec->lexicalGlobalObject(), asValue()); if (isBoolean()) - return constructBooleanFromImmediateBoolean(exec, asValue()); + return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue()); ASSERT(isUndefinedOrNull()); throwError(exec, createNotAnObjectError(exec, *this)); diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h index b2e7a51..098123e 100644 --- a/Source/JavaScriptCore/runtime/JSValue.h +++ b/Source/JavaScriptCore/runtime/JSValue.h @@ -37,6 +37,7 @@ namespace JSC { class Identifier; class JSCell; class JSGlobalData; + class JSGlobalObject; class JSImmediate; class JSObject; class JSString; @@ -52,11 +53,33 @@ namespace JSC { enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString }; + #if USE(JSVALUE32_64) typedef int64_t EncodedJSValue; #else typedef void* EncodedJSValue; #endif + + union EncodedValueDescriptor { + EncodedJSValue asEncodedJSValue; +#if USE(JSVALUE32_64) + double asDouble; +#elif USE(JSVALUE64) + JSCell* ptr; +#endif + +#if CPU(BIG_ENDIAN) + struct { + int32_t tag; + int32_t payload; + } asBits; +#else + struct { + int32_t payload; + int32_t tag; + } asBits; +#endif + }; double nonInlineNaN(); @@ -167,6 +190,7 @@ namespace JSC { UString toString(ExecState*) const; UString toPrimitiveString(ExecState*) const; JSObject* toObject(ExecState*) const; + JSObject* toObject(ExecState*, JSGlobalObject*) const; // Integer conversions. double toInteger(ExecState*) const; @@ -222,7 +246,7 @@ namespace JSC { JSValue(HashTableDeletedValueTag); inline const JSValue asValue() const { return *this; } - JSObject* toObjectSlowCase(ExecState*) const; + JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const; JSObject* toThisObjectSlowCase(ExecState*) const; JSObject* synthesizePrototype(ExecState*) const; @@ -239,28 +263,14 @@ namespace JSC { enum { DeletedValueTag = 0xfffffff8 }; enum { LowestTag = DeletedValueTag }; - + uint32_t tag() const; int32_t payload() const; - union { - EncodedJSValue asEncodedJSValue; - double asDouble; -#if CPU(BIG_ENDIAN) - struct { - int32_t tag; - int32_t payload; - } asBits; -#else - struct { - int32_t payload; - int32_t tag; - } asBits; -#endif - } u; -#else // USE(JSVALUE32_64) + EncodedValueDescriptor u; +#elif USE(JSVALUE64) JSCell* m_ptr; -#endif // USE(JSVALUE32_64) +#endif }; #if USE(JSVALUE32_64) @@ -392,9 +402,6 @@ namespace JSC { { JSValue v; v.u.asEncodedJSValue = encodedJSValue; -#if ENABLE(JSC_ZOMBIES) - ASSERT(!v.isZombie()); -#endif return v; } diff --git a/Source/JavaScriptCore/runtime/JSVariableObject.h b/Source/JavaScriptCore/runtime/JSVariableObject.h index e94d277..891ada8 100644 --- a/Source/JavaScriptCore/runtime/JSVariableObject.h +++ b/Source/JavaScriptCore/runtime/JSVariableObject.h @@ -44,7 +44,7 @@ namespace JSC { friend class JIT; public: - SymbolTable& symbolTable() const { return *d->symbolTable; } + SymbolTable& symbolTable() const { return *m_symbolTable; } virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0; @@ -54,39 +54,24 @@ namespace JSC { virtual bool isVariableObject() const; virtual bool isDynamicScope(bool& requiresDynamicChecks) const = 0; - WriteBarrier<Unknown>& registerAt(int index) const { return d->registers[index]; } + WriteBarrier<Unknown>& registerAt(int index) const { return m_registers[index]; } - static PassRefPtr<Structure> createStructure(JSValue prototype) + WriteBarrier<Unknown>* const * addressOfRegisters() const { return &m_registers; } + + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: static const unsigned StructureFlags = OverridesGetPropertyNames | JSObject::StructureFlags; - // Subclasses of JSVariableObject can subclass this struct to add data - // without increasing their own size (since there's a hard limit on the - // size of a JSCell). - struct JSVariableObjectData { - JSVariableObjectData(SymbolTable* symbolTable, Register* registers) - : symbolTable(symbolTable) - , registers(reinterpret_cast<WriteBarrier<Unknown>*>(registers)) - { - ASSERT(symbolTable); - } - - SymbolTable* symbolTable; // Maps name -> offset from "r" in register file. - WriteBarrier<Unknown>* registers; // "r" in the register file. - OwnArrayPtr<WriteBarrier<Unknown> > registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file. - - private: - JSVariableObjectData(const JSVariableObjectData&); - JSVariableObjectData& operator=(const JSVariableObjectData&); - }; - - JSVariableObject(NonNullPassRefPtr<Structure> structure, JSVariableObjectData* data) + + JSVariableObject(NonNullPassRefPtr<Structure> structure, SymbolTable* symbolTable, Register* registers) : JSNonFinalObject(structure) - , d(data) // Subclass owns this pointer. + , m_symbolTable(symbolTable) + , m_registers(reinterpret_cast<WriteBarrier<Unknown>*>(registers)) { + ASSERT(m_symbolTable); COMPILE_ASSERT(sizeof(WriteBarrier<Unknown>) == sizeof(Register), Register_should_be_same_size_as_WriteBarrier); } @@ -99,7 +84,9 @@ namespace JSC { bool symbolTablePut(JSGlobalData&, const Identifier&, JSValue); bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes); - JSVariableObjectData* d; + SymbolTable* m_symbolTable; // Maps name -> offset from "r" in register file. + WriteBarrier<Unknown>* m_registers; // "r" in the register file. + OwnArrayPtr<WriteBarrier<Unknown> > m_registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file. }; inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot) @@ -161,9 +148,9 @@ namespace JSC { inline void JSVariableObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray) { - ASSERT(registerArray != d->registerArray); - d->registerArray = registerArray; - d->registers = registers; + ASSERT(registerArray != m_registerArray); + m_registerArray = registerArray; + m_registers = registers; } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSWrapperObject.h b/Source/JavaScriptCore/runtime/JSWrapperObject.h index 6d586df..63833e9 100644 --- a/Source/JavaScriptCore/runtime/JSWrapperObject.h +++ b/Source/JavaScriptCore/runtime/JSWrapperObject.h @@ -30,19 +30,19 @@ namespace JSC { // Number, Boolean and Date which are wrappers for primitive types. class JSWrapperObject : public JSNonFinalObject { protected: - explicit JSWrapperObject(JSGlobalData&, NonNullPassRefPtr<Structure>); + explicit JSWrapperObject(NonNullPassRefPtr<Structure>); public: - JSValue internalValue() const { return m_internalValue.get(); } + JSValue internalValue() const; void setInternalValue(JSGlobalData&, JSValue); - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: - static const unsigned AnonymousSlotCount = 1 + JSObject::AnonymousSlotCount; + static const unsigned StructureFlags = OverridesMarkChildren | JSNonFinalObject::StructureFlags; private: virtual void markChildren(MarkStack&); @@ -50,10 +50,14 @@ namespace JSC { WriteBarrier<Unknown> m_internalValue; }; - inline JSWrapperObject::JSWrapperObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure) + inline JSWrapperObject::JSWrapperObject(NonNullPassRefPtr<Structure> structure) : JSNonFinalObject(structure) { - putAnonymousValue(globalData, 0, jsNull()); + } + + inline JSValue JSWrapperObject::internalValue() const + { + return m_internalValue.get(); } inline void JSWrapperObject::setInternalValue(JSGlobalData& globalData, JSValue value) @@ -61,7 +65,6 @@ namespace JSC { ASSERT(value); ASSERT(!value.isObject()); m_internalValue.set(globalData, this, value); - putAnonymousValue(globalData, 0, value); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSZombie.cpp b/Source/JavaScriptCore/runtime/JSZombie.cpp index c0c5f11..23cf135 100644 --- a/Source/JavaScriptCore/runtime/JSZombie.cpp +++ b/Source/JavaScriptCore/runtime/JSZombie.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "JSZombie.h" #include "ClassInfo.h" +#include "JSObject.h" #include "ScopeChain.h" #if ENABLE(JSC_ZOMBIES) @@ -38,7 +39,7 @@ Structure* JSZombie::leakedZombieStructure() { static Structure* structure = 0; if (!structure) { Structure::startIgnoringLeaks(); - structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType), 0, &info).leakRef(); + structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType), 0, &s_info).leakRef(); Structure::stopIgnoringLeaks(); } return structure; diff --git a/Source/JavaScriptCore/runtime/JSZombie.h b/Source/JavaScriptCore/runtime/JSZombie.h index 5fe6b6d..179ff53 100644 --- a/Source/JavaScriptCore/runtime/JSZombie.h +++ b/Source/JavaScriptCore/runtime/JSZombie.h @@ -66,9 +66,9 @@ public: virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&) { ASSERT_NOT_REACHED(); return false; } virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&) { ASSERT_NOT_REACHED(); return false; } - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, 0), AnonymousSlotCount, &s_info); } static const ClassInfo s_info; diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp index 4614a7c..3e205a1 100644 --- a/Source/JavaScriptCore/runtime/MachineStackMarker.cpp +++ b/Source/JavaScriptCore/runtime/MachineStackMarker.cpp @@ -28,6 +28,11 @@ #include "JSGlobalData.h" #include <setjmp.h> #include <stdlib.h> +#include <wtf/StdLibExtras.h> + +#if USE(PTHREAD_BASED_QT) && !defined(WTF_USE_PTHREADS) +#define WTF_USE_PTHREADS 1 +#endif #if OS(DARWIN) @@ -74,12 +79,14 @@ #if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) #include <signal.h> #ifndef SA_RESTART -#error MachineStackMarker requires SA_RESTART +#error MachineThreads requires SA_RESTART #endif #endif #endif +using namespace WTF; + namespace JSC { static inline void swapIfBackwards(void*& begin, void*& end) @@ -113,7 +120,7 @@ static void pthreadSignalHandlerSuspendResume(int signo) } #endif -class MachineStackMarker::Thread { +class MachineThreads::Thread { public: Thread(pthread_t pthread, const PlatformThread& platThread, void* base) : posixThread(pthread) @@ -142,20 +149,20 @@ public: #endif -MachineStackMarker::MachineStackMarker(Heap* heap) +MachineThreads::MachineThreads(Heap* heap) : m_heap(heap) #if ENABLE(JSC_MULTIPLE_THREADS) , m_registeredThreads(0) - , m_currentThreadRegistrar(0) + , m_threadSpecific(0) #endif { } -MachineStackMarker::~MachineStackMarker() +MachineThreads::~MachineThreads() { #if ENABLE(JSC_MULTIPLE_THREADS) - if (m_currentThreadRegistrar) { - int error = pthread_key_delete(m_currentThreadRegistrar); + if (m_threadSpecific) { + int error = pthread_key_delete(m_threadSpecific); ASSERT_UNUSED(error, !error); } @@ -181,24 +188,24 @@ static inline PlatformThread getCurrentPlatformThread() #endif } -void MachineStackMarker::makeUsableFromMultipleThreads() +void MachineThreads::makeUsableFromMultipleThreads() { - if (m_currentThreadRegistrar) + if (m_threadSpecific) return; - int error = pthread_key_create(&m_currentThreadRegistrar, unregisterThread); + int error = pthread_key_create(&m_threadSpecific, removeThread); if (error) CRASH(); } -void MachineStackMarker::registerThread() +void MachineThreads::addCurrentThread() { ASSERT(!m_heap->globalData()->exclusiveThread || m_heap->globalData()->exclusiveThread == currentThread()); - if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar)) + if (!m_threadSpecific || pthread_getspecific(m_threadSpecific)) return; - pthread_setspecific(m_currentThreadRegistrar, this); + pthread_setspecific(m_threadSpecific, this); Thread* thread = new Thread(pthread_self(), getCurrentPlatformThread(), m_heap->globalData()->stack().origin()); MutexLocker lock(m_registeredThreadsMutex); @@ -207,13 +214,13 @@ void MachineStackMarker::registerThread() m_registeredThreads = thread; } -void MachineStackMarker::unregisterThread(void* p) +void MachineThreads::removeThread(void* p) { if (p) - static_cast<MachineStackMarker*>(p)->unregisterThread(); + static_cast<MachineThreads*>(p)->removeCurrentThread(); } -void MachineStackMarker::unregisterThread() +void MachineThreads::removeCurrentThread() { pthread_t currentPosixThread = pthread_self(); @@ -240,21 +247,13 @@ void MachineStackMarker::unregisterThread() #endif -void NEVER_INLINE MachineStackMarker::markCurrentThreadConservativelyInternal(ConservativeSet& conservativeSet) -{ - void* begin = m_heap->globalData()->stack().current(); - void* end = m_heap->globalData()->stack().origin(); - swapIfBackwards(begin, end); - conservativeSet.add(begin, end); -} - #if COMPILER(GCC) #define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*)))) #else #define REGISTER_BUFFER_ALIGNMENT #endif -void MachineStackMarker::markCurrentThreadConservatively(ConservativeSet& conservativeSet) +void MachineThreads::gatherFromCurrentThread(ConservativeRoots& conservativeRoots, void* stackCurrent) { // setjmp forces volatile registers onto the stack jmp_buf registers REGISTER_BUFFER_ALIGNMENT; @@ -267,7 +266,15 @@ void MachineStackMarker::markCurrentThreadConservatively(ConservativeSet& conser #pragma warning(pop) #endif - markCurrentThreadConservativelyInternal(conservativeSet); + void* registersBegin = ®isters; + void* registersEnd = reinterpret_cast<void*>(roundUpToMultipleOf<sizeof(void*)>(reinterpret_cast<uintptr_t>(®isters + 1))); + swapIfBackwards(registersBegin, registersEnd); + conservativeRoots.add(registersBegin, registersEnd); + + void* stackBegin = stackCurrent; + void* stackEnd = m_heap->globalData()->stack().origin(); + swapIfBackwards(stackBegin, stackEnd); + conservativeRoots.add(stackBegin, stackEnd); } #if ENABLE(JSC_MULTIPLE_THREADS) @@ -431,20 +438,19 @@ static void freePlatformThreadRegisters(PlatformThreadRegisters& regs) #endif } -void MachineStackMarker::markOtherThreadConservatively(ConservativeSet& conservativeSet, Thread* thread) +void MachineThreads::gatherFromOtherThread(ConservativeRoots& conservativeRoots, Thread* thread) { suspendThread(thread->platformThread); PlatformThreadRegisters regs; size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs); - // mark the thread's registers - conservativeSet.add(static_cast<void*>(®s), static_cast<void*>(reinterpret_cast<char*>(®s) + regSize)); + conservativeRoots.add(static_cast<void*>(®s), static_cast<void*>(reinterpret_cast<char*>(®s) + regSize)); void* stackPointer = otherThreadStackPointer(regs); void* stackBase = thread->stackBase; swapIfBackwards(stackPointer, stackBase); - conservativeSet.add(stackPointer, stackBase); + conservativeRoots.add(stackPointer, stackBase); resumeThread(thread->platformThread); @@ -453,27 +459,27 @@ void MachineStackMarker::markOtherThreadConservatively(ConservativeSet& conserva #endif -void MachineStackMarker::markMachineStackConservatively(ConservativeSet& conservativeSet) +void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoots, void* stackCurrent) { - markCurrentThreadConservatively(conservativeSet); + gatherFromCurrentThread(conservativeRoots, stackCurrent); #if ENABLE(JSC_MULTIPLE_THREADS) - if (m_currentThreadRegistrar) { + if (m_threadSpecific) { MutexLocker lock(m_registeredThreadsMutex); #ifndef NDEBUG - // Forbid malloc during the mark phase. Marking a thread suspends it, so - // a malloc inside markChildren() would risk a deadlock with a thread that had been - // suspended while holding the malloc lock. + // Forbid malloc during the gather phase. The gather phase suspends + // threads, so a malloc during gather would risk a deadlock with a + // thread that had been suspended while holding the malloc lock. fastMallocForbid(); #endif // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held, // and since this is a shared heap, they are real locks. for (Thread* thread = m_registeredThreads; thread; thread = thread->next) { if (!pthread_equal(thread->posixThread, pthread_self())) - markOtherThreadConservatively(conservativeSet, thread); + gatherFromOtherThread(conservativeRoots, thread); } #ifndef NDEBUG fastMallocAllow(); diff --git a/Source/JavaScriptCore/runtime/MachineStackMarker.h b/Source/JavaScriptCore/runtime/MachineStackMarker.h index 8afdb46..c814ac5 100644 --- a/Source/JavaScriptCore/runtime/MachineStackMarker.h +++ b/Source/JavaScriptCore/runtime/MachineStackMarker.h @@ -19,8 +19,8 @@ * */ -#ifndef MachineStackMarker_h -#define MachineStackMarker_h +#ifndef MachineThreads_h +#define MachineThreads_h #include <wtf/Noncopyable.h> #include <wtf/ThreadingPrimitives.h> @@ -32,32 +32,31 @@ namespace JSC { class Heap; - class ConservativeSet; + class ConservativeRoots; - class MachineStackMarker { - WTF_MAKE_NONCOPYABLE(MachineStackMarker); + class MachineThreads { + WTF_MAKE_NONCOPYABLE(MachineThreads); public: - MachineStackMarker(Heap*); - ~MachineStackMarker(); + MachineThreads(Heap*); + ~MachineThreads(); - void markMachineStackConservatively(ConservativeSet&); + void gatherConservativeRoots(ConservativeRoots&, void* stackCurrent); #if ENABLE(JSC_MULTIPLE_THREADS) void makeUsableFromMultipleThreads(); - void registerThread(); // Only needs to be called by clients that can use the same heap from multiple threads. + void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads. #endif private: - void markCurrentThreadConservatively(ConservativeSet&); - void markCurrentThreadConservativelyInternal(ConservativeSet&); + void gatherFromCurrentThread(ConservativeRoots&, void* stackCurrent); #if ENABLE(JSC_MULTIPLE_THREADS) class Thread; - static void unregisterThread(void*); + static void removeThread(void*); + void removeCurrentThread(); - void unregisterThread(); - void markOtherThreadConservatively(ConservativeSet&, Thread*); + void gatherFromOtherThread(ConservativeRoots&, Thread*); #endif Heap* m_heap; @@ -65,10 +64,10 @@ namespace JSC { #if ENABLE(JSC_MULTIPLE_THREADS) Mutex m_registeredThreadsMutex; Thread* m_registeredThreads; - pthread_key_t m_currentThreadRegistrar; + pthread_key_t m_threadSpecific; #endif }; } // namespace JSC -#endif // MachineStackMarker_h +#endif // MachineThreads_h diff --git a/Source/JavaScriptCore/runtime/MarkStack.cpp b/Source/JavaScriptCore/runtime/MarkStack.cpp index a350c35..e9d1b13 100644 --- a/Source/JavaScriptCore/runtime/MarkStack.cpp +++ b/Source/JavaScriptCore/runtime/MarkStack.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,6 +26,14 @@ #include "config.h" #include "MarkStack.h" +#include "ConservativeSet.h" +#include "Heap.h" +#include "JSArray.h" +#include "JSCell.h" +#include "JSObject.h" +#include "ScopeChain.h" +#include "Structure.h" + namespace JSC { size_t MarkStack::s_pageSize = 0; @@ -37,4 +45,83 @@ void MarkStack::compact() m_markSets.shrinkAllocation(s_pageSize); } +void MarkStack::append(ConservativeRoots& conservativeRoots) +{ + JSCell** roots = conservativeRoots.roots(); + size_t size = conservativeRoots.size(); + for (size_t i = 0; i < size; ++i) + internalAppend(roots[i]); } + +inline void MarkStack::markChildren(JSCell* cell) +{ + ASSERT(Heap::isMarked(cell)); + if (!cell->structure()->typeInfo().overridesMarkChildren()) { +#ifdef NDEBUG + asObject(cell)->markChildrenDirect(*this); +#else + ASSERT(!m_isCheckingForDefaultMarkViolation); + m_isCheckingForDefaultMarkViolation = true; + cell->markChildren(*this); + ASSERT(m_isCheckingForDefaultMarkViolation); + m_isCheckingForDefaultMarkViolation = false; +#endif + return; + } + if (cell->vptr() == m_jsArrayVPtr) { + asArray(cell)->markChildrenDirect(*this); + return; + } + cell->markChildren(*this); +} + +void MarkStack::drain() +{ +#if !ASSERT_DISABLED + ASSERT(!m_isDraining); + m_isDraining = true; +#endif + while (!m_markSets.isEmpty() || !m_values.isEmpty()) { + while (!m_markSets.isEmpty() && m_values.size() < 50) { + ASSERT(!m_markSets.isEmpty()); + MarkSet& current = m_markSets.last(); + ASSERT(current.m_values); + JSValue* end = current.m_end; + ASSERT(current.m_values); + ASSERT(current.m_values != end); + findNextUnmarkedNullValue: + ASSERT(current.m_values != end); + JSValue value = *current.m_values; + current.m_values++; + + JSCell* cell; + if (!value || !value.isCell() || Heap::testAndSetMarked(cell = value.asCell())) { + if (current.m_values == end) { + m_markSets.removeLast(); + continue; + } + goto findNextUnmarkedNullValue; + } + + if (cell->structure()->typeInfo().type() < CompoundType) { + if (current.m_values == end) { + m_markSets.removeLast(); + continue; + } + goto findNextUnmarkedNullValue; + } + + if (current.m_values == end) + m_markSets.removeLast(); + + markChildren(cell); + } + while (!m_values.isEmpty()) + markChildren(m_values.removeLast()); + } +#if !ASSERT_DISABLED + m_isDraining = false; +#endif +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/MarkStack.h b/Source/JavaScriptCore/runtime/MarkStack.h index 0b7941e..7131917 100644 --- a/Source/JavaScriptCore/runtime/MarkStack.h +++ b/Source/JavaScriptCore/runtime/MarkStack.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,6 +27,7 @@ #define MarkStack_h #include "JSValue.h" +#include "Register.h" #include "WriteBarrier.h" #include <wtf/Vector.h> #include <wtf/Noncopyable.h> @@ -34,6 +35,7 @@ namespace JSC { + class ConservativeRoots; class JSGlobalData; class Register; @@ -50,7 +52,13 @@ namespace JSC { #endif { } - + + ~MarkStack() + { + ASSERT(m_markSets.isEmpty()); + ASSERT(m_values.isEmpty()); + } + void deprecatedAppend(JSValue*); void deprecatedAppend(JSCell**); void deprecatedAppend(Register*); @@ -70,17 +78,18 @@ namespace JSC { if (count) m_markSets.append(MarkSet(values, values + count, properties)); } + + void append(ConservativeRoots&); - inline void drain(); + void drain(); void compact(); - ~MarkStack() - { - ASSERT(m_markSets.isEmpty()); - ASSERT(m_values.isEmpty()); - } - private: + friend class HeapRootMarker; // Allowed to mark a JSValue* or JSCell** directly. + void append(JSValue*); + void append(JSValue*, size_t count); + void append(JSCell**); + void internalAppend(JSCell*); void internalAppend(JSValue); void markChildren(JSCell*); @@ -196,7 +205,105 @@ namespace JSC { bool m_isDraining; #endif }; + + inline void MarkStack::append(JSValue* slot, size_t count) + { + if (!count) + return; + m_markSets.append(MarkSet(slot, slot + count, NoNullValues)); + } + + template <typename T> inline void MarkStack::append(DeprecatedPtr<T>* slot) + { + internalAppend(*slot->slot()); + } -} + template <typename T> inline void MarkStack::append(WriteBarrierBase<T>* slot) + { + internalAppend(*slot->slot()); + } + + ALWAYS_INLINE void MarkStack::deprecatedAppend(JSCell** value) + { + ASSERT(value); + internalAppend(*value); + } + + ALWAYS_INLINE void MarkStack::deprecatedAppend(JSValue* value) + { + ASSERT(value); + internalAppend(*value); + } + + ALWAYS_INLINE void MarkStack::append(JSValue* value) + { + ASSERT(value); + internalAppend(*value); + } + + ALWAYS_INLINE void MarkStack::append(JSCell** value) + { + ASSERT(value); + internalAppend(*value); + } + + ALWAYS_INLINE void MarkStack::deprecatedAppend(Register* value) + { + ASSERT(value); + internalAppend(value->jsValue()); + } + + ALWAYS_INLINE void MarkStack::internalAppend(JSValue value) + { + ASSERT(value); + if (value.isCell()) + internalAppend(value.asCell()); + } + + // Privileged class for marking JSValues directly. It is only safe to use + // this class to mark direct heap roots that are marked during every GC pass. + // All other references should be wrapped in WriteBarriers and marked through + // the MarkStack. + class HeapRootMarker { + private: + friend class Heap; + HeapRootMarker(MarkStack&); + + public: + void mark(JSValue*); + void mark(JSValue*, size_t); + void mark(JSString**); + void mark(JSCell**); + + private: + MarkStack& m_markStack; + }; + + inline HeapRootMarker::HeapRootMarker(MarkStack& markStack) + : m_markStack(markStack) + { + } + + inline void HeapRootMarker::mark(JSValue* slot) + { + m_markStack.append(slot); + } + + inline void HeapRootMarker::mark(JSValue* slot, size_t count) + { + m_markStack.append(slot, count); + } + + inline void HeapRootMarker::mark(JSString** slot) + { + m_markStack.append(reinterpret_cast<JSCell**>(slot)); + } + + inline void HeapRootMarker::mark(JSCell** slot) + { + m_markStack.append(slot); + } + +} // namespace JSC #endif diff --git a/Source/JavaScriptCore/runtime/MarkedBlock.cpp b/Source/JavaScriptCore/runtime/MarkedBlock.cpp index 48dda4c..cae701f 100644 --- a/Source/JavaScriptCore/runtime/MarkedBlock.cpp +++ b/Source/JavaScriptCore/runtime/MarkedBlock.cpp @@ -27,6 +27,8 @@ #include "MarkedBlock.h" #include "JSCell.h" +#include "JSObject.h" +#include "JSZombie.h" #include "ScopeChain.h" namespace JSC { diff --git a/Source/JavaScriptCore/runtime/MarkedBlock.h b/Source/JavaScriptCore/runtime/MarkedBlock.h index e80fe82..0e2b59c 100644 --- a/Source/JavaScriptCore/runtime/MarkedBlock.h +++ b/Source/JavaScriptCore/runtime/MarkedBlock.h @@ -24,6 +24,7 @@ #include <wtf/Bitmap.h> #include <wtf/PageAllocationAligned.h> +#include <wtf/StdLibExtras.h> namespace JSC { @@ -35,15 +36,6 @@ namespace JSC { static const size_t KB = 1024; - // Efficient implementation that takes advantage of powers of two. - template<size_t divisor> inline size_t roundUpToMultipleOf(size_t x) - { - COMPILE_ASSERT(divisor && !(divisor & (divisor - 1)), divisor_is_a_power_of_two); - - size_t remainderMask = divisor - 1; - return (x + remainderMask) & ~remainderMask; - } - class MarkedBlock { public: static const size_t atomSize = sizeof(double); // Ensures natural alignment for all built-in types. @@ -109,7 +101,7 @@ namespace JSC { inline size_t MarkedBlock::firstAtom() { - return roundUpToMultipleOf<atomSize>(sizeof(MarkedBlock)) / atomSize; + return WTF::roundUpToMultipleOf<atomSize>(sizeof(MarkedBlock)) / atomSize; } inline MarkedBlock::Atom* MarkedBlock::atoms() diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.cpp b/Source/JavaScriptCore/runtime/MarkedSpace.cpp index 15ab514..d9a1e42 100644 --- a/Source/JavaScriptCore/runtime/MarkedSpace.cpp +++ b/Source/JavaScriptCore/runtime/MarkedSpace.cpp @@ -24,6 +24,7 @@ #include "JSCell.h" #include "JSGlobalData.h" #include "JSLock.h" +#include "JSObject.h" #include "ScopeChain.h" namespace JSC { @@ -35,7 +36,10 @@ MarkedSpace::MarkedSpace(JSGlobalData* globalData) , m_highWaterMark(0) , m_globalData(globalData) { - for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) + for (size_t cellSize = preciseStep; cellSize < preciseCutoff; cellSize += preciseStep) + sizeClassFor(cellSize).cellSize = cellSize; + + for (size_t cellSize = impreciseStep; cellSize < impreciseCutoff; cellSize += impreciseStep) sizeClassFor(cellSize).cellSize = cellSize; } @@ -148,7 +152,10 @@ void MarkedSpace::reset() { m_waterMark = 0; - for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) + for (size_t cellSize = preciseStep; cellSize < preciseCutoff; cellSize += preciseStep) + sizeClassFor(cellSize).reset(); + + for (size_t cellSize = impreciseStep; cellSize < impreciseCutoff; cellSize += impreciseStep) sizeClassFor(cellSize).reset(); BlockIterator end = m_blocks.end(); diff --git a/Source/JavaScriptCore/runtime/MarkedSpace.h b/Source/JavaScriptCore/runtime/MarkedSpace.h index 2e88887..29a8cd0 100644 --- a/Source/JavaScriptCore/runtime/MarkedSpace.h +++ b/Source/JavaScriptCore/runtime/MarkedSpace.h @@ -32,8 +32,7 @@ #include <wtf/Noncopyable.h> #include <wtf/Vector.h> -#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= MarkedSpace::maxCellSize, class_fits_in_cell) -#define ASSERT_CLASS_FILLS_CELL(class) COMPILE_ASSERT(sizeof(class) == MarkedSpace::maxCellSize, class_fills_cell) +#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) < MarkedSpace::maxCellSize, class_fits_in_cell) namespace JSC { @@ -48,7 +47,7 @@ namespace JSC { WTF_MAKE_NONCOPYABLE(MarkedSpace); public: // Currently public for use in assertions. - static const size_t maxCellSize = 64; + static const size_t maxCellSize = 1024; static Heap* heap(JSCell*); @@ -81,10 +80,15 @@ namespace JSC { template<typename Functor> void forEach(Functor&); private: - // [ 8, 16... 64 ] + // [ 8, 16... 128 ) static const size_t preciseStep = MarkedBlock::atomSize; - static const size_t preciseCutoff = maxCellSize; - static const size_t preciseCount = preciseCutoff / preciseStep; + static const size_t preciseCutoff = 128; + static const size_t preciseCount = preciseCutoff / preciseStep - 1; + + // [ 128, 256... 1024 ) + static const size_t impreciseStep = preciseCutoff; + static const size_t impreciseCutoff = maxCellSize; + static const size_t impreciseCount = impreciseCutoff / impreciseStep - 1; typedef HashSet<MarkedBlock*>::iterator BlockIterator; @@ -106,6 +110,7 @@ namespace JSC { void clearMarks(MarkedBlock*); SizeClass m_preciseSizeClasses[preciseCount]; + SizeClass m_impreciseSizeClasses[impreciseCount]; HashSet<MarkedBlock*> m_blocks; size_t m_waterMark; size_t m_highWaterMark; diff --git a/Source/JavaScriptCore/runtime/MathObject.h b/Source/JavaScriptCore/runtime/MathObject.h index 86e7951..26eaae0 100644 --- a/Source/JavaScriptCore/runtime/MathObject.h +++ b/Source/JavaScriptCore/runtime/MathObject.h @@ -34,9 +34,9 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: diff --git a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp index 7949dd9..d8fda69 100644 --- a/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp +++ b/Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp @@ -41,7 +41,7 @@ NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, JSGlobalObject* putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5 putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | ReadOnly | DontEnum); - m_errorStructure = ErrorInstance::createStructure(prototype); + m_errorStructure = ErrorInstance::createStructure(exec->globalData(), prototype); } static EncodedJSValue JSC_HOST_CALL constructWithNativeErrorConstructor(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/NativeErrorConstructor.h b/Source/JavaScriptCore/runtime/NativeErrorConstructor.h index e4978cc..23f798e 100644 --- a/Source/JavaScriptCore/runtime/NativeErrorConstructor.h +++ b/Source/JavaScriptCore/runtime/NativeErrorConstructor.h @@ -35,9 +35,9 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } Structure* errorStructure() { return m_errorStructure.get(); } diff --git a/Source/JavaScriptCore/runtime/NumberConstructor.cpp b/Source/JavaScriptCore/runtime/NumberConstructor.cpp index 3e4d6c7..aee143a 100644 --- a/Source/JavaScriptCore/runtime/NumberConstructor.cpp +++ b/Source/JavaScriptCore/runtime/NumberConstructor.cpp @@ -104,7 +104,7 @@ static JSValue numberConstructorMinValue(ExecState*, JSValue, const Identifier&) // ECMA 15.7.1 static EncodedJSValue JSC_HOST_CALL constructWithNumberConstructor(ExecState* exec) { - NumberObject* object = new (exec) NumberObject(exec->globalData(), exec->lexicalGlobalObject()->numberObjectStructure()); + NumberObject* object = new (exec) NumberObject(exec->globalData(), asInternalFunction(exec->callee())->globalObject()->numberObjectStructure()); double n = exec->argumentCount() ? exec->argument(0).toNumber(exec) : 0; object->setInternalValue(exec->globalData(), jsNumber(n)); return JSValue::encode(object); diff --git a/Source/JavaScriptCore/runtime/NumberConstructor.h b/Source/JavaScriptCore/runtime/NumberConstructor.h index aaf7c32..ab4507e 100644 --- a/Source/JavaScriptCore/runtime/NumberConstructor.h +++ b/Source/JavaScriptCore/runtime/NumberConstructor.h @@ -37,9 +37,9 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue proto) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue }; diff --git a/Source/JavaScriptCore/runtime/NumberObject.cpp b/Source/JavaScriptCore/runtime/NumberObject.cpp index 4408673..74b5e98 100644 --- a/Source/JavaScriptCore/runtime/NumberObject.cpp +++ b/Source/JavaScriptCore/runtime/NumberObject.cpp @@ -31,8 +31,8 @@ ASSERT_CLASS_FITS_IN_CELL(NumberObject); const ClassInfo NumberObject::s_info = { "Number", &JSWrapperObject::s_info, 0, 0 }; -NumberObject::NumberObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(globalData, structure) +NumberObject::NumberObject(JSGlobalData&, NonNullPassRefPtr<Structure> structure) + : JSWrapperObject(structure) { ASSERT(inherits(&s_info)); } @@ -42,9 +42,9 @@ JSValue NumberObject::getJSNumber() return internalValue(); } -NumberObject* constructNumber(ExecState* exec, JSValue number) +NumberObject* constructNumber(ExecState* exec, JSGlobalObject* globalObject, JSValue number) { - NumberObject* object = new (exec) NumberObject(exec->globalData(), exec->lexicalGlobalObject()->numberObjectStructure()); + NumberObject* object = new (exec) NumberObject(exec->globalData(), globalObject->numberObjectStructure()); object->setInternalValue(exec->globalData(), number); return object; } diff --git a/Source/JavaScriptCore/runtime/NumberObject.h b/Source/JavaScriptCore/runtime/NumberObject.h index 8a80382..90d0b26 100644 --- a/Source/JavaScriptCore/runtime/NumberObject.h +++ b/Source/JavaScriptCore/runtime/NumberObject.h @@ -31,19 +31,16 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } - protected: - static const unsigned StructureFlags = JSWrapperObject::StructureFlags; - private: virtual JSValue getJSNumber(); }; - NumberObject* constructNumber(ExecState*, JSValue); + NumberObject* constructNumber(ExecState*, JSGlobalObject*, JSValue); } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp index 5080ef8..c642a5b 100644 --- a/Source/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/Source/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -95,18 +95,18 @@ bool ObjectConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifi } // ECMA 15.2.2 -static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, const ArgList& args) +static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args) { JSValue arg = args.at(0); if (arg.isUndefinedOrNull()) - return constructEmptyObject(exec); - return arg.toObject(exec); + return constructEmptyObject(exec, globalObject); + return arg.toObject(exec, globalObject); } static EncodedJSValue JSC_HOST_CALL constructWithObjectConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructObject(exec, args)); + return JSValue::encode(constructObject(exec, asInternalFunction(exec->callee())->globalObject(), args)); } ConstructType ObjectConstructor::getConstructData(ConstructData& constructData) @@ -118,7 +118,7 @@ ConstructType ObjectConstructor::getConstructData(ConstructData& constructData) static EncodedJSValue JSC_HOST_CALL callObjectConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructObject(exec, args)); + return JSValue::encode(constructObject(exec, asInternalFunction(exec->callee())->globalObject(), args)); } CallType ObjectConstructor::getCallData(CallData& callData) diff --git a/Source/JavaScriptCore/runtime/ObjectConstructor.h b/Source/JavaScriptCore/runtime/ObjectConstructor.h index 895f988..b7bfc1d 100644 --- a/Source/JavaScriptCore/runtime/ObjectConstructor.h +++ b/Source/JavaScriptCore/runtime/ObjectConstructor.h @@ -36,9 +36,9 @@ namespace JSC { static const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: diff --git a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h index 85a3818..c000dc8 100644 --- a/Source/JavaScriptCore/runtime/PropertyMapHashTable.h +++ b/Source/JavaScriptCore/runtime/PropertyMapHashTable.h @@ -291,7 +291,7 @@ inline PropertyTable::~PropertyTable() { iterator end = this->end(); for (iterator iter = begin(); iter != end; ++iter) - iter->key->ref(); + iter->key->deref(); fastFree(m_index); } diff --git a/Source/JavaScriptCore/runtime/PropertyNameArray.cpp b/Source/JavaScriptCore/runtime/PropertyNameArray.cpp index 351ecc3..8efb406 100644 --- a/Source/JavaScriptCore/runtime/PropertyNameArray.cpp +++ b/Source/JavaScriptCore/runtime/PropertyNameArray.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "PropertyNameArray.h" +#include "JSObject.h" #include "ScopeChain.h" #include "Structure.h" #include "StructureChain.h" diff --git a/Source/JavaScriptCore/runtime/PutPropertySlot.h b/Source/JavaScriptCore/runtime/PutPropertySlot.h index 4c9e0e6..69d1f8b 100644 --- a/Source/JavaScriptCore/runtime/PutPropertySlot.h +++ b/Source/JavaScriptCore/runtime/PutPropertySlot.h @@ -45,14 +45,14 @@ namespace JSC { { } - void setExistingProperty(DeprecatedPtr<JSObject> base, size_t offset) + void setExistingProperty(JSObject* base, size_t offset) { m_type = ExistingProperty; m_base = base; m_offset = offset; } - void setNewProperty(DeprecatedPtr<JSObject> base, size_t offset) + void setNewProperty(JSObject* base, size_t offset) { m_type = NewProperty; m_base = base; @@ -60,7 +60,7 @@ namespace JSC { } Type type() const { return m_type; } - JSObject* base() const { return m_base.get(); } + JSObject* base() const { return m_base; } bool isStrictMode() const { return m_isStrictMode; } bool isCacheable() const { return m_type != Uncachable; } @@ -68,9 +68,10 @@ namespace JSC { ASSERT(isCacheable()); return m_offset; } + private: Type m_type; - DeprecatedPtr<JSObject> m_base; + JSObject* m_base; size_t m_offset; bool m_isStrictMode; }; diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp index 95ce5e9..25cb2d5 100644 --- a/Source/JavaScriptCore/runtime/RegExp.cpp +++ b/Source/JavaScriptCore/runtime/RegExp.cpp @@ -34,6 +34,38 @@ namespace JSC { +RegExpFlags regExpFlags(const UString& string) +{ + RegExpFlags flags = NoFlags; + + for (unsigned i = 0; i < string.length(); ++i) { + switch (string.characters()[i]) { + case 'g': + if (flags & FlagGlobal) + return InvalidFlags; + flags = static_cast<RegExpFlags>(flags | FlagGlobal); + break; + + case 'i': + if (flags & FlagIgnoreCase) + return InvalidFlags; + flags = static_cast<RegExpFlags>(flags | FlagIgnoreCase); + break; + + case 'm': + if (flags & FlagMultiline) + return InvalidFlags; + flags = static_cast<RegExpFlags>(flags | FlagMultiline); + break; + + default: + return InvalidFlags; + } + } + + return flags; +} + struct RegExpRepresentation { #if ENABLE(YARR_JIT) Yarr::YarrCodeBlock m_regExpJITCode; @@ -41,9 +73,9 @@ struct RegExpRepresentation { OwnPtr<Yarr::BytecodePattern> m_regExpBytecode; }; -inline RegExp::RegExp(JSGlobalData* globalData, const UString& patternString, const UString& flags) +inline RegExp::RegExp(JSGlobalData* globalData, const UString& patternString, RegExpFlags flags) : m_patternString(patternString) - , m_flagBits(0) + , m_flags(flags) , m_constructionError(0) , m_numSubpatterns(0) #if ENABLE(REGEXP_TRACING) @@ -52,17 +84,6 @@ inline RegExp::RegExp(JSGlobalData* globalData, const UString& patternString, co #endif , m_representation(adoptPtr(new RegExpRepresentation)) { - // NOTE: The global flag is handled on a case-by-case basis by functions like - // String::match and RegExpObject::match. - if (!flags.isNull()) { - if (flags.find('g') != notFound) - m_flagBits |= Global; - if (flags.find('i') != notFound) - m_flagBits |= IgnoreCase; - if (flags.find('m') != notFound) - m_flagBits |= Multiline; - } - m_state = compile(globalData); } @@ -70,7 +91,7 @@ RegExp::~RegExp() { } -PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& patternString, const UString& flags) +PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& patternString, RegExpFlags flags) { RefPtr<RegExp> res = adoptRef(new RegExp(globalData, patternString, flags)); #if ENABLE(REGEXP_TRACING) diff --git a/Source/JavaScriptCore/runtime/RegExp.h b/Source/JavaScriptCore/runtime/RegExp.h index d99befb..000c33a 100644 --- a/Source/JavaScriptCore/runtime/RegExp.h +++ b/Source/JavaScriptCore/runtime/RegExp.h @@ -24,6 +24,7 @@ #include "UString.h" #include "ExecutableAllocator.h" +#include "RegExpKey.h" #include <wtf/Forward.h> #include <wtf/RefCounted.h> @@ -32,18 +33,20 @@ namespace JSC { struct RegExpRepresentation; class JSGlobalData; + RegExpFlags regExpFlags(const UString&); + class RegExp : public RefCounted<RegExp> { public: - static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern, const UString& flags); + static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern, RegExpFlags); ~RegExp(); - bool global() const { return m_flagBits & Global; } - bool ignoreCase() const { return m_flagBits & IgnoreCase; } - bool multiline() const { return m_flagBits & Multiline; } + bool global() const { return m_flags & FlagGlobal; } + bool ignoreCase() const { return m_flags & FlagIgnoreCase; } + bool multiline() const { return m_flags & FlagMultiline; } const UString& pattern() const { return m_patternString; } - bool isValid() const { return !m_constructionError; } + bool isValid() const { return !m_constructionError && m_flags != InvalidFlags; } const char* errorMessage() const { return m_constructionError; } int match(const UString&, int startOffset, Vector<int, 32>* ovector = 0); @@ -54,7 +57,7 @@ namespace JSC { #endif private: - RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags); + RegExp(JSGlobalData* globalData, const UString& pattern, RegExpFlags); enum RegExpState { ParseError, @@ -68,9 +71,8 @@ namespace JSC { void matchCompareWithInterpreter(const UString&, int startOffset, int* offsetVector, int jitResult); #endif - enum FlagBits { Global = 1, IgnoreCase = 2, Multiline = 4 }; UString m_patternString; - int m_flagBits; + RegExpFlags m_flags; const char* m_constructionError; unsigned m_numSubpatterns; #if ENABLE(REGEXP_TRACING) diff --git a/Source/JavaScriptCore/runtime/RegExpCache.cpp b/Source/JavaScriptCore/runtime/RegExpCache.cpp index d101758..c96b047 100644 --- a/Source/JavaScriptCore/runtime/RegExpCache.cpp +++ b/Source/JavaScriptCore/runtime/RegExpCache.cpp @@ -31,7 +31,7 @@ namespace JSC { -PassRefPtr<RegExp> RegExpCache::lookupOrCreate(const UString& patternString, const UString& flags) +PassRefPtr<RegExp> RegExpCache::lookupOrCreate(const UString& patternString, RegExpFlags flags) { if (patternString.length() < maxCacheablePatternLength) { pair<RegExpCacheMap::iterator, bool> result = m_cacheMap.add(RegExpKey(flags, patternString), 0); @@ -43,7 +43,7 @@ PassRefPtr<RegExp> RegExpCache::lookupOrCreate(const UString& patternString, con return create(patternString, flags, m_cacheMap.end()); } -PassRefPtr<RegExp> RegExpCache::create(const UString& patternString, const UString& flags, RegExpCacheMap::iterator iterator) +PassRefPtr<RegExp> RegExpCache::create(const UString& patternString, RegExpFlags flags, RegExpCacheMap::iterator iterator) { RefPtr<RegExp> regExp = RegExp::create(m_globalData, patternString, flags); diff --git a/Source/JavaScriptCore/runtime/RegExpCache.h b/Source/JavaScriptCore/runtime/RegExpCache.h index b5b637f..b4a6ae5 100644 --- a/Source/JavaScriptCore/runtime/RegExpCache.h +++ b/Source/JavaScriptCore/runtime/RegExpCache.h @@ -41,8 +41,8 @@ class RegExpCache { typedef HashMap<RegExpKey, RefPtr<RegExp> > RegExpCacheMap; public: - PassRefPtr<RegExp> lookupOrCreate(const UString& patternString, const UString& flags); - PassRefPtr<RegExp> create(const UString& patternString, const UString& flags, RegExpCacheMap::iterator iterator); + PassRefPtr<RegExp> lookupOrCreate(const UString& patternString, RegExpFlags); + PassRefPtr<RegExp> create(const UString& patternString, RegExpFlags, RegExpCacheMap::iterator); RegExpCache(JSGlobalData* globalData); private: diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp index c06fdc4..19b4b36 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -291,9 +291,9 @@ void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValu { asRegExpConstructor(baseObject)->setMultiline(value.toBoolean(exec)); } - + // ECMA 15.10.4 -JSObject* constructRegExp(ExecState* exec, const ArgList& args) +JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args) { JSValue arg0 = args.at(0); JSValue arg1 = args.at(1); @@ -305,18 +305,28 @@ JSObject* constructRegExp(ExecState* exec, const ArgList& args) } UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec); - UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec); + if (exec->hadException()) + return 0; + + RegExpFlags flags = NoFlags; + if (!arg1.isUndefined()) { + flags = regExpFlags(arg1.toString(exec)); + if (exec->hadException()) + return 0; + if (flags == InvalidFlags) + return throwError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor.")); + } RefPtr<RegExp> regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags); if (!regExp->isValid()) return throwError(exec, createSyntaxError(exec, regExp->errorMessage())); - return new (exec) RegExpObject(exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp.release()); + return new (exec) RegExpObject(exec->lexicalGlobalObject(), globalObject->regExpStructure(), regExp.release()); } static EncodedJSValue JSC_HOST_CALL constructWithRegExpConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructRegExp(exec, args)); + return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args)); } ConstructType RegExpConstructor::getConstructData(ConstructData& constructData) @@ -329,7 +339,7 @@ ConstructType RegExpConstructor::getConstructData(ConstructData& constructData) static EncodedJSValue JSC_HOST_CALL callRegExpConstructor(ExecState* exec) { ArgList args(exec); - return JSValue::encode(constructRegExp(exec, args)); + return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args)); } CallType RegExpConstructor::getCallData(CallData& callData) diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.h b/Source/JavaScriptCore/runtime/RegExpConstructor.h index 8a8a54a..5e0b2b8 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.h +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.h @@ -59,9 +59,9 @@ namespace JSC { public: RegExpConstructor(ExecState*, JSGlobalObject*, NonNullPassRefPtr<Structure>, RegExpPrototype*); - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); @@ -96,7 +96,7 @@ namespace JSC { RegExpConstructor* asRegExpConstructor(JSValue); - JSObject* constructRegExp(ExecState*, const ArgList&); + JSObject* constructRegExp(ExecState*, JSGlobalObject*, const ArgList&); inline RegExpConstructor* asRegExpConstructor(JSValue value) { diff --git a/Source/JavaScriptCore/runtime/RegExpKey.h b/Source/JavaScriptCore/runtime/RegExpKey.h index cd1368d..b4847f9 100644 --- a/Source/JavaScriptCore/runtime/RegExpKey.h +++ b/Source/JavaScriptCore/runtime/RegExpKey.h @@ -25,63 +25,54 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "UString.h" -#include <wtf/text/StringHash.h> - #ifndef RegExpKey_h #define RegExpKey_h +#include "UString.h" +#include <wtf/text/StringHash.h> + namespace JSC { +enum RegExpFlags { + NoFlags = 0, + FlagGlobal = 1, + FlagIgnoreCase = 2, + FlagMultiline = 4, + InvalidFlags = 8, + DeletedValueFlags = -1 +}; + struct RegExpKey { - int flagsValue; + RegExpFlags flagsValue; RefPtr<StringImpl> pattern; RegExpKey() - : flagsValue(0) + : flagsValue(NoFlags) { } - RegExpKey(int flags) + RegExpKey(RegExpFlags flags) : flagsValue(flags) { } - RegExpKey(int flags, const UString& pattern) + RegExpKey(RegExpFlags flags, const UString& pattern) : flagsValue(flags) , pattern(pattern.impl()) { } - RegExpKey(int flags, const PassRefPtr<StringImpl> pattern) + RegExpKey(RegExpFlags flags, const PassRefPtr<StringImpl> pattern) : flagsValue(flags) , pattern(pattern) { } - RegExpKey(int flags, const RefPtr<StringImpl>& pattern) + RegExpKey(RegExpFlags flags, const RefPtr<StringImpl>& pattern) : flagsValue(flags) , pattern(pattern) { } - - RegExpKey(const UString& flags, const UString& pattern) - : pattern(pattern.impl()) - { - flagsValue = getFlagsValue(flags); - } - - int getFlagsValue(const UString flags) - { - flagsValue = 0; - if (flags.find('g') != notFound) - flagsValue += 4; - if (flags.find('i') != notFound) - flagsValue += 2; - if (flags.find('m') != notFound) - flagsValue += 1; - return flagsValue; - } }; inline bool operator==(const RegExpKey& a, const RegExpKey& b) @@ -112,8 +103,8 @@ template<> struct DefaultHash<JSC::RegExpKey> { }; template<> struct HashTraits<JSC::RegExpKey> : GenericHashTraits<JSC::RegExpKey> { - static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = -1; } - static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == -1; } + static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = JSC::DeletedValueFlags; } + static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == JSC::DeletedValueFlags; } }; } // namespace WTF diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp index 5baf884..4b5028b 100644 --- a/Source/JavaScriptCore/runtime/RegExpObject.cpp +++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp @@ -63,7 +63,7 @@ const ClassInfo RegExpObject::s_info = { "RegExp", &JSObjectWithGlobalObject::s_ RegExpObject::RegExpObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<RegExp> regExp) : JSObjectWithGlobalObject(globalObject, structure) - , d(adoptPtr(new RegExpObjectData(regExp, 0))) + , d(adoptPtr(new RegExpObjectData(regExp))) { ASSERT(inherits(&s_info)); } @@ -72,6 +72,13 @@ RegExpObject::~RegExpObject() { } +void RegExpObject::markChildren(MarkStack& markStack) +{ + Base::markChildren(markStack); + if (UNLIKELY(!d->lastIndex.get().isInt32())) + markStack.append(&d->lastIndex); +} + bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot); @@ -104,7 +111,7 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&) JSValue regExpObjectLastIndex(ExecState*, JSValue slotBase, const Identifier&) { - return jsNumber(asRegExpObject(slotBase)->lastIndex()); + return asRegExpObject(slotBase)->getLastIndex(); } void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) @@ -114,7 +121,7 @@ void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue value) { - asRegExpObject(baseObject)->setLastIndex(value.toInteger(exec)); + asRegExpObject(baseObject)->setLastIndex(exec->globalData(), value); } JSValue RegExpObject::test(ExecState* exec) @@ -133,12 +140,7 @@ JSValue RegExpObject::exec(ExecState* exec) bool RegExpObject::match(ExecState* exec) { RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); - - UString input = !exec->argumentCount() ? regExpConstructor->input() : exec->argument(0).toString(exec); - if (input.isNull()) { - throwError(exec, createError(exec, makeUString("No input to ", toString(exec), "."))); - return false; - } + UString input = exec->argument(0).toString(exec); if (!regExp()->global()) { int position; @@ -147,20 +149,32 @@ bool RegExpObject::match(ExecState* exec) return position >= 0; } - if (d->lastIndex < 0 || d->lastIndex > input.length()) { - d->lastIndex = 0; - return false; + JSValue jsLastIndex = getLastIndex(); + unsigned lastIndex; + if (LIKELY(jsLastIndex.isUInt32())) { + lastIndex = jsLastIndex.asUInt32(); + if (lastIndex > input.length()) { + setLastIndex(0); + return false; + } + } else { + double doubleLastIndex = jsLastIndex.toInteger(exec); + if (doubleLastIndex < 0 || doubleLastIndex > input.length()) { + setLastIndex(0); + return false; + } + lastIndex = static_cast<unsigned>(doubleLastIndex); } int position; int length = 0; - regExpConstructor->performMatch(d->regExp.get(), input, static_cast<int>(d->lastIndex), position, length); + regExpConstructor->performMatch(d->regExp.get(), input, lastIndex, position, length); if (position < 0) { - d->lastIndex = 0; + setLastIndex(0); return false; } - d->lastIndex = position + length; + setLastIndex(position + length); return true; } diff --git a/Source/JavaScriptCore/runtime/RegExpObject.h b/Source/JavaScriptCore/runtime/RegExpObject.h index 1f89b84..fa2024d 100644 --- a/Source/JavaScriptCore/runtime/RegExpObject.h +++ b/Source/JavaScriptCore/runtime/RegExpObject.h @@ -28,14 +28,26 @@ namespace JSC { class RegExpObject : public JSObjectWithGlobalObject { public: + typedef JSObjectWithGlobalObject Base; + RegExpObject(JSGlobalObject* globalObject, NonNullPassRefPtr<Structure>, NonNullPassRefPtr<RegExp>); virtual ~RegExpObject(); void setRegExp(PassRefPtr<RegExp> r) { d->regExp = r; } RegExp* regExp() const { return d->regExp.get(); } - void setLastIndex(double lastIndex) { d->lastIndex = lastIndex; } - double lastIndex() const { return d->lastIndex; } + void setLastIndex(size_t lastIndex) + { + d->lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex)); + } + void setLastIndex(JSGlobalData& globalData, JSValue lastIndex) + { + d->lastIndex.set(globalData, this, lastIndex); + } + JSValue getLastIndex() const + { + return d->lastIndex.get(); + } JSValue test(ExecState*); JSValue exec(ExecState*); @@ -46,28 +58,30 @@ namespace JSC { static JS_EXPORTDATA const ClassInfo s_info; - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: - static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObjectWithGlobalObject::StructureFlags; - + static const unsigned StructureFlags = OverridesMarkChildren | OverridesGetOwnPropertySlot | JSObjectWithGlobalObject::StructureFlags; + private: + virtual void markChildren(MarkStack&); + bool match(ExecState*); struct RegExpObjectData { WTF_MAKE_FAST_ALLOCATED; public: - RegExpObjectData(NonNullPassRefPtr<RegExp> regExp, double lastIndex) + RegExpObjectData(NonNullPassRefPtr<RegExp> regExp) : regExp(regExp) - , lastIndex(lastIndex) { + lastIndex.setWithoutWriteBarrier(jsNumber(0)); } RefPtr<RegExp> regExp; - double lastIndex; + WriteBarrier<Unknown> lastIndex; }; #if COMPILER(MSVC) friend void WTF::deleteOwnedPtr<RegExpObjectData>(RegExpObjectData*); diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp index 106006c..61747b1 100644 --- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -48,11 +48,11 @@ static EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*); // ECMA 15.10.5 RegExpPrototype::RegExpPrototype(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, Structure* functionStructure) - : RegExpObject(globalObject, structure, RegExp::create(&exec->globalData(), "", "")) + : RegExpObject(globalObject, structure, RegExp::create(&exec->globalData(), "", NoFlags)) { - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum); - putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().test, regExpProtoFuncTest), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 2, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().test, regExpProtoFuncTest), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum); } @@ -90,7 +90,17 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec) regExp = asRegExpObject(arg0)->regExp(); } else { UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec); - UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + + RegExpFlags flags = NoFlags; + if (!arg1.isUndefined()) { + flags = regExpFlags(arg1.toString(exec)); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + if (flags == InvalidFlags) + return throwVMError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor.")); + } regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags); } diff --git a/Source/JavaScriptCore/runtime/ScopeChain.h b/Source/JavaScriptCore/runtime/ScopeChain.h index fbecd11..cb70a34 100644 --- a/Source/JavaScriptCore/runtime/ScopeChain.h +++ b/Source/JavaScriptCore/runtime/ScopeChain.h @@ -64,7 +64,7 @@ namespace JSC { void print(); #endif - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, 0); } virtual void markChildren(MarkStack&); private: static const unsigned StructureFlags = OverridesMarkChildren; @@ -100,7 +100,7 @@ namespace JSC { bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; } private: - DeprecatedPtr<ScopeChainNode> m_node; + ScopeChainNode* m_node; }; inline ScopeChainIterator ScopeChainNode::begin() @@ -128,6 +128,17 @@ namespace JSC { { return scopeChain()->globalThis.get(); } + + ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const + { + return static_cast<ScopeChainNode*>(jsValue().asCell()); + } + + ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain) + { + *this = JSValue(scopeChain); + return *this; + } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/SmallStrings.cpp b/Source/JavaScriptCore/runtime/SmallStrings.cpp index 9b193f5..ac67020 100644 --- a/Source/JavaScriptCore/runtime/SmallStrings.cpp +++ b/Source/JavaScriptCore/runtime/SmallStrings.cpp @@ -33,8 +33,6 @@ namespace JSC { -static const unsigned numCharactersToStore = 0x100; - static inline bool isMarked(JSCell* string) { return string && Heap::isMarked(string); @@ -45,17 +43,22 @@ class SmallStringsStorage { public: SmallStringsStorage(); - StringImpl* rep(unsigned char character) { return m_reps[character].get(); } + StringImpl* rep(unsigned char character) + { + return m_reps[character].get(); + } private: - RefPtr<StringImpl> m_reps[numCharactersToStore]; + static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1; + + RefPtr<StringImpl> m_reps[singleCharacterStringCount]; }; SmallStringsStorage::SmallStringsStorage() { UChar* characterBuffer = 0; - RefPtr<StringImpl> baseString = StringImpl::createUninitialized(numCharactersToStore, characterBuffer); - for (unsigned i = 0; i < numCharactersToStore; ++i) { + RefPtr<StringImpl> baseString = StringImpl::createUninitialized(singleCharacterStringCount, characterBuffer); + for (unsigned i = 0; i < singleCharacterStringCount; ++i) { characterBuffer[i] = i; m_reps[i] = StringImpl::create(baseString, i, 1); } @@ -63,7 +66,7 @@ SmallStringsStorage::SmallStringsStorage() SmallStrings::SmallStrings() { - COMPILE_ASSERT(numCharactersToStore == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage); + COMPILE_ASSERT(singleCharacterStringCount == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage); clear(); } @@ -71,7 +74,7 @@ SmallStrings::~SmallStrings() { } -void SmallStrings::markChildren(MarkStack& markStack) +void SmallStrings::markChildren(HeapRootMarker& heapRootMarker) { /* Our hypothesis is that small strings are very common. So, we cache them @@ -83,9 +86,9 @@ void SmallStrings::markChildren(MarkStack& markStack) so, it's probably reasonable to mark the rest. If not, we clear the cache. */ - bool isAnyStringMarked = isMarked(m_emptyString.get()); - for (unsigned i = 0; i < numCharactersToStore && !isAnyStringMarked; ++i) - isAnyStringMarked = isMarked(m_singleCharacterStrings[i].get()); + bool isAnyStringMarked = isMarked(m_emptyString); + for (unsigned i = 0; i < singleCharacterStringCount && !isAnyStringMarked; ++i) + isAnyStringMarked = isMarked(m_singleCharacterStrings[i]); if (!isAnyStringMarked) { clear(); @@ -93,17 +96,17 @@ void SmallStrings::markChildren(MarkStack& markStack) } if (m_emptyString) - markStack.append(&m_emptyString); - for (unsigned i = 0; i < numCharactersToStore; ++i) { + heapRootMarker.mark(&m_emptyString); + for (unsigned i = 0; i < singleCharacterStringCount; ++i) { if (m_singleCharacterStrings[i]) - markStack.append(&m_singleCharacterStrings[i]); + heapRootMarker.mark(&m_singleCharacterStrings[i]); } } void SmallStrings::clear() { m_emptyString = 0; - for (unsigned i = 0; i < numCharactersToStore; ++i) + for (unsigned i = 0; i < singleCharacterStringCount; ++i) m_singleCharacterStrings[i] = 0; } @@ -112,7 +115,7 @@ unsigned SmallStrings::count() const unsigned count = 0; if (m_emptyString) ++count; - for (unsigned i = 0; i < numCharactersToStore; ++i) { + for (unsigned i = 0; i < singleCharacterStringCount; ++i) { if (m_singleCharacterStrings[i]) ++count; } diff --git a/Source/JavaScriptCore/runtime/SmallStrings.h b/Source/JavaScriptCore/runtime/SmallStrings.h index cd9c325..b54d020 100644 --- a/Source/JavaScriptCore/runtime/SmallStrings.h +++ b/Source/JavaScriptCore/runtime/SmallStrings.h @@ -33,13 +33,16 @@ namespace JSC { + class HeapRootMarker; class JSGlobalData; class JSString; class MarkStack; class SmallStringsStorage; + static const unsigned maxSingleCharacterString = 0xFF; + class SmallStrings { - WTF_MAKE_NONCOPYABLE(SmallStrings); WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_NONCOPYABLE(SmallStrings); public: SmallStrings(); ~SmallStrings(); @@ -48,30 +51,33 @@ namespace JSC { { if (!m_emptyString) createEmptyString(globalData); - return m_emptyString.get(); + return m_emptyString; } + JSString* singleCharacterString(JSGlobalData* globalData, unsigned char character) { if (!m_singleCharacterStrings[character]) createSingleCharacterString(globalData, character); - return m_singleCharacterStrings[character].get(); + return m_singleCharacterStrings[character]; } StringImpl* singleCharacterStringRep(unsigned char character); - void markChildren(MarkStack&); + void markChildren(HeapRootMarker&); void clear(); unsigned count() const; - JSCell** singleCharacterStrings() { return m_singleCharacterStrings[0].slot(); } + JSString** singleCharacterStrings() { return &m_singleCharacterStrings[0]; } private: + static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1; + void createEmptyString(JSGlobalData*); void createSingleCharacterString(JSGlobalData*, unsigned char); - DeprecatedPtr<JSString> m_emptyString; - FixedArray<DeprecatedPtr<JSString>, 0x100> m_singleCharacterStrings; + JSString* m_emptyString; + JSString* m_singleCharacterStrings[singleCharacterStringCount]; OwnPtr<SmallStringsStorage> m_storage; }; diff --git a/Source/JavaScriptCore/runtime/StringConstructor.cpp b/Source/JavaScriptCore/runtime/StringConstructor.cpp index 5398f31..ed088e4 100644 --- a/Source/JavaScriptCore/runtime/StringConstructor.cpp +++ b/Source/JavaScriptCore/runtime/StringConstructor.cpp @@ -67,9 +67,10 @@ StringConstructor::StringConstructor(ExecState* exec, JSGlobalObject* globalObje // ECMA 15.5.2 static EncodedJSValue JSC_HOST_CALL constructWithStringConstructor(ExecState* exec) { + JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject(); if (!exec->argumentCount()) - return JSValue::encode(new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure())); - return JSValue::encode(new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure(), exec->argument(0).toString(exec))); + return JSValue::encode(new (exec) StringObject(exec, globalObject->stringObjectStructure())); + return JSValue::encode(new (exec) StringObject(exec, globalObject->stringObjectStructure(), exec->argument(0).toString(exec))); } ConstructType StringConstructor::getConstructData(ConstructData& constructData) diff --git a/Source/JavaScriptCore/runtime/StringObject.cpp b/Source/JavaScriptCore/runtime/StringObject.cpp index 5fe7544..47e5860 100644 --- a/Source/JavaScriptCore/runtime/StringObject.cpp +++ b/Source/JavaScriptCore/runtime/StringObject.cpp @@ -30,21 +30,21 @@ ASSERT_CLASS_FITS_IN_CELL(StringObject); const ClassInfo StringObject::s_info = { "String", &JSWrapperObject::s_info, 0, 0 }; StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure) - : JSWrapperObject(exec->globalData(), structure) + : JSWrapperObject(structure) { ASSERT(inherits(&s_info)); setInternalValue(exec->globalData(), jsEmptyString(exec)); } StringObject::StringObject(JSGlobalData& globalData, NonNullPassRefPtr<Structure> structure, JSString* string) - : JSWrapperObject(globalData, structure) + : JSWrapperObject(structure) { ASSERT(inherits(&s_info)); setInternalValue(globalData, string); } StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string) - : JSWrapperObject(exec->globalData(), structure) + : JSWrapperObject(structure) { ASSERT(inherits(&s_info)); setInternalValue(exec->globalData(), jsString(exec, string)); diff --git a/Source/JavaScriptCore/runtime/StringObject.h b/Source/JavaScriptCore/runtime/StringObject.h index 99f9add..ae3376d 100644 --- a/Source/JavaScriptCore/runtime/StringObject.h +++ b/Source/JavaScriptCore/runtime/StringObject.h @@ -31,7 +31,7 @@ namespace JSC { StringObject(ExecState*, NonNullPassRefPtr<Structure>); StringObject(ExecState*, NonNullPassRefPtr<Structure>, const UString&); - static StringObject* create(ExecState*, JSString*); + static StringObject* create(ExecState*, JSGlobalObject*, JSString*); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); @@ -45,15 +45,15 @@ namespace JSC { JSString* internalValue() const { return asString(JSWrapperObject::internalValue());} - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } protected: - static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSWrapperObject::StructureFlags; + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSWrapperObject::StructureFlags; StringObject(JSGlobalData&, NonNullPassRefPtr<Structure>, JSString*); - }; + }; StringObject* asStringObject(JSValue); diff --git a/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h b/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h index 0a44ed3..e4c7061 100644 --- a/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h +++ b/Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h @@ -33,7 +33,7 @@ namespace JSC { static StringObjectThatMasqueradesAsUndefined* create(ExecState* exec, const UString& string) { return new (exec) StringObjectThatMasqueradesAsUndefined(exec, - createStructure(exec->lexicalGlobalObject()->stringPrototype()), string); + createStructure(exec->globalData(), exec->lexicalGlobalObject()->stringPrototype()), string); } private: @@ -42,9 +42,9 @@ namespace JSC { { } - static PassRefPtr<Structure> createStructure(JSValue proto) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static const unsigned StructureFlags = OverridesGetOwnPropertySlot | MasqueradesAsUndefined | OverridesGetPropertyNames | StringObject::StructureFlags; diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp index aa37122..a6bf4e6 100644 --- a/Source/JavaScriptCore/runtime/StringPrototype.cpp +++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp @@ -604,9 +604,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec) JSValue a0 = exec->argument(0); - UString u = s; RefPtr<RegExp> reg; - RegExpObject* imp = 0; if (a0.inherits(&RegExpObject::s_info)) reg = asRegExpObject(a0)->regExp(); else { @@ -615,12 +613,12 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec) * If regexp is not an object whose [[Class]] property is "RegExp", it is * replaced with the result of the expression new RegExp(regexp). */ - reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString()); + reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), NoFlags); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; int matchLength = 0; - regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength); + regExpConstructor->performMatch(reg.get(), s, 0, pos, matchLength); if (!(reg->global())) { // case without 'g' flag is handled like RegExp.prototype.exec if (pos < 0) @@ -630,15 +628,13 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec) // return array of matches MarkedArgumentBuffer list; - int lastIndex = 0; + unsigned lastIndex = 0; while (pos >= 0) { - list.append(jsSubstring(exec, u, pos, matchLength)); + list.append(jsSubstring(exec, s, pos, matchLength)); lastIndex = pos; pos += matchLength == 0 ? 1 : matchLength; - regExpConstructor->performMatch(reg.get(), u, pos, pos, matchLength); + regExpConstructor->performMatch(reg.get(), s, pos, pos, matchLength); } - if (imp) - imp->setLastIndex(lastIndex); if (list.isEmpty()) { // if there are no matches at all, it's important to return // Null instead of an empty array, because this matches @@ -658,7 +654,6 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec) JSValue a0 = exec->argument(0); - UString u = s; RefPtr<RegExp> reg; if (a0.inherits(&RegExpObject::s_info)) reg = asRegExpObject(a0)->regExp(); @@ -668,12 +663,12 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec) * If regexp is not an object whose [[Class]] property is "RegExp", it is * replaced with the result of the expression new RegExp(regexp). */ - reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString()); + reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), NoFlags); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; int matchLength = 0; - regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength); + regExpConstructor->performMatch(reg.get(), s, 0, pos, matchLength); return JSValue::encode(jsNumber(pos)); } diff --git a/Source/JavaScriptCore/runtime/StringPrototype.h b/Source/JavaScriptCore/runtime/StringPrototype.h index feea2e2..57def22 100644 --- a/Source/JavaScriptCore/runtime/StringPrototype.h +++ b/Source/JavaScriptCore/runtime/StringPrototype.h @@ -34,12 +34,18 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); - static PassRefPtr<Structure> createStructure(JSValue prototype) + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); + return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); } static const ClassInfo s_info; + + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | StringObject::StructureFlags; + + COMPILE_ASSERT(!StringObject::AnonymousSlotCount, StringPrototype_stomps_on_your_anonymous_slot); + static const unsigned AnonymousSlotCount = 1; }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h index bf27334..c9f900a 100644 --- a/Source/JavaScriptCore/runtime/Structure.h +++ b/Source/JavaScriptCore/runtime/Structure.h @@ -32,7 +32,6 @@ #include "PropertyMapHashTable.h" #include "PropertyNameArray.h" #include "Protect.h" -#include "StructureChain.h" #include "StructureTransitionTable.h" #include "JSTypeInfo.h" #include "UString.h" @@ -46,6 +45,7 @@ namespace JSC { class MarkStack; class PropertyNameArray; class PropertyNameArrayData; + class StructureChain; struct ClassInfo; @@ -56,13 +56,18 @@ namespace JSC { class Structure : public RefCounted<Structure> { public: - friend class JIT; friend class StructureTransitionTable; - static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo) + static PassRefPtr<Structure> create(JSGlobalData&, JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo) { return adoptRef(new Structure(prototype, typeInfo, anonymousSlotCount, classInfo)); } + enum VPtrStealingHackType { VPtrStealingHack }; + static PassRefPtr<Structure> create(VPtrStealingHackType, const ClassInfo* classInfo) + { + return adoptRef(new Structure(jsNull(), TypeInfo(UnspecifiedType), 0, classInfo)); + } + static void startIgnoringLeaks(); static void stopIgnoringLeaks(); @@ -102,6 +107,7 @@ namespace JSC { DeprecatedPtr<Unknown>* storedPrototypeSlot() { return &m_prototype; } JSValue prototypeForLookup(ExecState*) const; StructureChain* prototypeChain(ExecState*) const; + DeprecatedPtr<StructureChain>* cachedPrototypeChainSlot() { return &m_cachedPrototypeChain; } Structure* previousID() const { return m_previous.get(); } @@ -140,6 +146,21 @@ namespace JSC { static void initializeThreading(); + static ptrdiff_t prototypeOffset() + { + return OBJECT_OFFSETOF(Structure, m_prototype); + } + + static ptrdiff_t typeInfoFlagsOffset() + { + return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::flagsOffset(); + } + + static ptrdiff_t typeInfoTypeOffset() + { + return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::typeOffset(); + } + private: Structure(JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount, const ClassInfo*); Structure(const Structure*); @@ -190,7 +211,7 @@ namespace JSC { TypeInfo m_typeInfo; DeprecatedPtr<Unknown> m_prototype; - mutable RefPtr<StructureChain> m_cachedPrototypeChain; + mutable DeprecatedPtr<StructureChain> m_cachedPrototypeChain; RefPtr<Structure> m_previous; RefPtr<StringImpl> m_nameInPrevious; diff --git a/Source/JavaScriptCore/runtime/StructureChain.cpp b/Source/JavaScriptCore/runtime/StructureChain.cpp index e4523c3..4fa4a4b 100644 --- a/Source/JavaScriptCore/runtime/StructureChain.cpp +++ b/Source/JavaScriptCore/runtime/StructureChain.cpp @@ -32,7 +32,8 @@ namespace JSC { -StructureChain::StructureChain(Structure* head) +StructureChain::StructureChain(NonNullPassRefPtr<Structure> structure, Structure* head) + : JSCell(structure.releaseRef()) { size_t size = 0; for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure()) diff --git a/Source/JavaScriptCore/runtime/StructureChain.h b/Source/JavaScriptCore/runtime/StructureChain.h index 816b66d..88592dc 100644 --- a/Source/JavaScriptCore/runtime/StructureChain.h +++ b/Source/JavaScriptCore/runtime/StructureChain.h @@ -26,6 +26,8 @@ #ifndef StructureChain_h #define StructureChain_h +#include "JSCell.h" + #include <wtf/OwnArrayPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -35,15 +37,16 @@ namespace JSC { class Structure; - class StructureChain : public RefCounted<StructureChain> { + class StructureChain : public JSCell { friend class JIT; public: - static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); } + static StructureChain* create(JSGlobalData& globalData, Structure* head) { return new (&globalData) StructureChain(globalData.structureChainStructure, head); } RefPtr<Structure>* head() { return m_vector.get(); } + static PassRefPtr<Structure> createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesMarkChildren), 0, 0); } private: - StructureChain(Structure* head); + StructureChain(NonNullPassRefPtr<Structure>, Structure* head); OwnArrayPtr<RefPtr<Structure> > m_vector; }; diff --git a/Source/JavaScriptCore/runtime/TimeoutChecker.cpp b/Source/JavaScriptCore/runtime/TimeoutChecker.cpp index 04d904d..d3867d4 100644 --- a/Source/JavaScriptCore/runtime/TimeoutChecker.cpp +++ b/Source/JavaScriptCore/runtime/TimeoutChecker.cpp @@ -101,7 +101,7 @@ static inline unsigned getCPUTime() // use a relative time from first call in order to avoid an overflow static double firstTime = currentTime(); - return (currentTime() - firstTime) * 1000; + return static_cast<unsigned> ((currentTime() - firstTime) * 1000); #endif } diff --git a/Source/JavaScriptCore/runtime/WriteBarrier.h b/Source/JavaScriptCore/runtime/WriteBarrier.h index 44840ad..af018a8 100644 --- a/Source/JavaScriptCore/runtime/WriteBarrier.h +++ b/Source/JavaScriptCore/runtime/WriteBarrier.h @@ -35,6 +35,7 @@ class JSGlobalData; typedef enum { } Unknown; typedef JSValue* HandleSlot; +// FIXME: Remove all uses of this class. template <class T> class DeprecatedPtr { public: DeprecatedPtr() : m_cell(0) { } @@ -54,6 +55,7 @@ protected: JSCell* m_cell; }; +// FIXME: Remove all uses of this class. template <> class DeprecatedPtr<Unknown> { public: DeprecatedPtr() { } @@ -73,17 +75,23 @@ private: JSValue m_value; }; -template <typename T> struct WriteBarrierCheck { +template <typename U, typename V> inline bool operator==(const DeprecatedPtr<U>& lhs, const DeprecatedPtr<V>& rhs) +{ + return lhs.get() == rhs.get(); +} + +template <typename T> struct JSValueChecker { static const bool IsJSValue = false; }; -template <> struct WriteBarrierCheck<JSValue> { +template <> struct JSValueChecker<JSValue> { static const bool IsJSValue = true; }; +// We have a separate base class with no constructors for use in Unions. template <typename T> class WriteBarrierBase { public: - COMPILE_ASSERT(!WriteBarrierCheck<T>::IsJSValue, WriteBarrier_JSValue_is_invalid__use_unknown); + COMPILE_ASSERT(!JSValueChecker<T>::IsJSValue, WriteBarrier_JSValue_is_invalid__use_unknown); void set(JSGlobalData&, const JSCell*, T* value) { this->m_cell = reinterpret_cast<JSCell*>(value); } T* get() const { return reinterpret_cast<T*>(m_cell); } @@ -100,20 +108,10 @@ public: void setWithoutWriteBarrier(T* value) { this->m_cell = reinterpret_cast<JSCell*>(value); } -protected: +private: JSCell* m_cell; }; -template <typename T> class WriteBarrier : public WriteBarrierBase<T> { -public: - WriteBarrier() { this->m_cell = 0; } - WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value) - { - this->set(globalData, owner, value); - } - -}; - template <> class WriteBarrierBase<Unknown> { public: void set(JSGlobalData&, const JSCell*, JSValue value) { m_value = JSValue::encode(value); } @@ -138,29 +136,41 @@ public: operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; } bool operator!() const { return !get(); } -protected: +private: EncodedJSValue m_value; }; +template <typename T> class WriteBarrier : public WriteBarrierBase<T> { +public: + WriteBarrier() + { + this->setWithoutWriteBarrier(0); + } + + WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value) + { + this->set(globalData, owner, value); + } +}; + template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> { public: - WriteBarrier() { m_value = JSValue::encode(JSValue()); } + WriteBarrier() + { + this->setWithoutWriteBarrier(JSValue()); + } + WriteBarrier(JSGlobalData& globalData, const JSCell* owner, JSValue value) { this->set(globalData, owner, value); } }; -template <typename U, typename V> inline bool operator==(const DeprecatedPtr<U>& lhs, const DeprecatedPtr<V>& rhs) -{ - return lhs.get() == rhs.get(); -} - template <typename U, typename V> inline bool operator==(const WriteBarrierBase<U>& lhs, const WriteBarrierBase<V>& rhs) { return lhs.get() == rhs.get(); } -} +} // namespace JSC #endif // WriteBarrier_h diff --git a/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_input.js b/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_input.js index 01c145c..26db14c 100644 --- a/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_input.js +++ b/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_input.js @@ -50,40 +50,40 @@ testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /\\d+/.exec('2345')", String(["2345"]), String(/\d+/.exec('2345'))); - // RegExp.input = "abcd12357efg"; /\d+/.exec() + // RegExp.input = "abcd12357efg"; /\d+/.exec(RegExp.input) RegExp.input = "abcd12357efg"; - testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /\\d+/.exec()", - String(["12357"]), String(/\d+/.exec())); + testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /\\d+/.exec(RegExp.input)", + String(["12357"]), String(/\d+/.exec(RegExp.input))); - // RegExp.input = "abcd12357efg"; /[h-z]+/.exec() + // RegExp.input = "abcd12357efg"; /[h-z]+/.exec(RegExp.input) RegExp.input = "abcd12357efg"; - testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /[h-z]+/.exec()", - null, /[h-z]+/.exec()); + testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /[h-z]+/.exec(RegExp.input)", + null, /[h-z]+/.exec(RegExp.input)); // RegExp.input = "abcd12357efg"; /\d+/.test('2345') RegExp.input = "abcd12357efg"; testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /\\d+/.test('2345')", true, /\d+/.test('2345')); - // RegExp.input = "abcd12357efg"; /\d+/.test() + // RegExp.input = "abcd12357efg"; /\d+/.test(RegExp.input) RegExp.input = "abcd12357efg"; - testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /\\d+/.test()", - true, /\d+/.test()); + testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /\\d+/.test(RegExp.input)", + true, /\d+/.test(RegExp.input)); - // RegExp.input = "abcd12357efg"; (new RegExp('d+')).test() + // RegExp.input = "abcd12357efg"; (new RegExp('d+')).test(RegExp.input) RegExp.input = "abcd12357efg"; - testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; (new RegExp('d+')).test()", - true, (new RegExp('d+')).test()); + testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; (new RegExp('d+')).test(RegExp.input)", + true, (new RegExp('d+')).test(RegExp.input)); - // RegExp.input = "abcd12357efg"; /[h-z]+/.test() + // RegExp.input = "abcd12357efg"; /[h-z]+/.test(RegExp.input) RegExp.input = "abcd12357efg"; - testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /[h-z]+/.test()", - false, /[h-z]+/.test()); + testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /[h-z]+/.test(RegExp.input)", + false, /[h-z]+/.test(RegExp.input)); - // RegExp.input = "abcd12357efg"; (new RegExp('[h-z]+')).test() + // RegExp.input = "abcd12357efg"; (new RegExp('[h-z]+')).test(RegExp.input) RegExp.input = "abcd12357efg"; - testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; (new RegExp('[h-z]+')).test()", - false, (new RegExp('[h-z]+')).test()); + testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; (new RegExp('[h-z]+')).test(RegExp.input)", + false, (new RegExp('[h-z]+')).test(RegExp.input)); function test() { diff --git a/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_input_as_array.js b/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_input_as_array.js index a1ed113..9afdb14 100644 --- a/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_input_as_array.js +++ b/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_input_as_array.js @@ -50,40 +50,40 @@ testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /\\d+/.exec('2345')", String(["2345"]), String(/\d+/.exec('2345'))); - // RegExp['$_'] = "abcd12357efg"; /\d+/.exec() + // RegExp['$_'] = "abcd12357efg"; /\d+/.exec(RegExp.input) RegExp['$_'] = "abcd12357efg"; - testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /\\d+/.exec()", - String(["12357"]), String(/\d+/.exec())); + testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /\\d+/.exec(RegExp.input)", + String(["12357"]), String(/\d+/.exec(RegExp.input))); - // RegExp['$_'] = "abcd12357efg"; /[h-z]+/.exec() + // RegExp['$_'] = "abcd12357efg"; /[h-z]+/.exec(RegExp.input) RegExp['$_'] = "abcd12357efg"; - testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /[h-z]+/.exec()", - null, /[h-z]+/.exec()); + testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /[h-z]+/.exec(RegExp.input)", + null, /[h-z]+/.exec(RegExp.input)); // RegExp['$_'] = "abcd12357efg"; /\d+/.test('2345') RegExp['$_'] = "abcd12357efg"; testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /\\d+/.test('2345')", true, /\d+/.test('2345')); - // RegExp['$_'] = "abcd12357efg"; /\d+/.test() + // RegExp['$_'] = "abcd12357efg"; /\d+/.test(RegExp.input) RegExp['$_'] = "abcd12357efg"; - testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /\\d+/.test()", - true, /\d+/.test()); + testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /\\d+/.test(RegExp.input)", + true, /\d+/.test(RegExp.input)); - // RegExp['$_'] = "abcd12357efg"; /[h-z]+/.test() + // RegExp['$_'] = "abcd12357efg"; /[h-z]+/.test(RegExp.input) RegExp['$_'] = "abcd12357efg"; - testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /[h-z]+/.test()", - false, /[h-z]+/.test()); + testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /[h-z]+/.test(RegExp.input)", + false, /[h-z]+/.test(RegExp.input)); - // RegExp['$_'] = "abcd12357efg"; (new RegExp('\d+')).test() + // RegExp['$_'] = "abcd12357efg"; (new RegExp('\d+')).test(RegExp.input) RegExp['$_'] = "abcd12357efg"; - testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; (new RegExp('\d+')).test()", - true, (new RegExp('\d+')).test()); + testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; (new RegExp('\d+')).test(RegExp.input)", + true, (new RegExp('\d+')).test(RegExp.input)); - // RegExp['$_'] = "abcd12357efg"; (new RegExp('[h-z]+')).test() + // RegExp['$_'] = "abcd12357efg"; (new RegExp('[h-z]+')).test(RegExp.input) RegExp['$_'] = "abcd12357efg"; - testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; (new RegExp('[h-z]+')).test()", - false, (new RegExp('[h-z]+')).test()); + testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; (new RegExp('[h-z]+')).test(RegExp.input)", + false, (new RegExp('[h-z]+')).test(RegExp.input)); function test() { diff --git a/Source/JavaScriptCore/wtf/Assertions.cpp b/Source/JavaScriptCore/wtf/Assertions.cpp index 3c4fc77..77e30c1 100644 --- a/Source/JavaScriptCore/wtf/Assertions.cpp +++ b/Source/JavaScriptCore/wtf/Assertions.cpp @@ -24,6 +24,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// The vprintf_stderr_common function triggers this error in the Mac build. +// Feel free to remove this pragma if this file builds on Mac. +// According to http://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas +// we need to place this directive before any data or functions are defined. +#pragma GCC diagnostic ignored "-Wmissing-format-attribute" + #include "config.h" #include "Assertions.h" diff --git a/Source/JavaScriptCore/wtf/Assertions.h b/Source/JavaScriptCore/wtf/Assertions.h index 13ece31..1d108e4 100644 --- a/Source/JavaScriptCore/wtf/Assertions.h +++ b/Source/JavaScriptCore/wtf/Assertions.h @@ -142,14 +142,14 @@ typedef struct { WTFLogChannelState state; } WTFLogChannel; -void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion); -void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6); -void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion); -void WTFReportBacktrace(); -void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5); -void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5); -void WTFLog(WTFLogChannel* channel, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3); -void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6); +WTF_EXPORT_PRIVATE void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion); +WTF_EXPORT_PRIVATE void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6); +WTF_EXPORT_PRIVATE void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion); +WTF_EXPORT_PRIVATE void WTFReportBacktrace(); +WTF_EXPORT_PRIVATE void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5); +WTF_EXPORT_PRIVATE void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5); +WTF_EXPORT_PRIVATE void WTFLog(WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3); +WTF_EXPORT_PRIVATE void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6); #ifdef __cplusplus } diff --git a/Source/JavaScriptCore/wtf/Atomics.h b/Source/JavaScriptCore/wtf/Atomics.h index 1d190a3..1ebd487 100644 --- a/Source/JavaScriptCore/wtf/Atomics.h +++ b/Source/JavaScriptCore/wtf/Atomics.h @@ -78,7 +78,7 @@ namespace WTF { #if OS(WINDOWS) -#define WTF_USE_LOCKFREE_THREADSAFESHARED 1 +#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1 #if COMPILER(MINGW) || COMPILER(MSVC7_OR_LOWER) || OS(WINCE) inline int atomicIncrement(int* addend) { return InterlockedIncrement(reinterpret_cast<long*>(addend)); } @@ -89,7 +89,7 @@ inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(r #endif #elif OS(DARWIN) -#define WTF_USE_LOCKFREE_THREADSAFESHARED 1 +#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1 inline int atomicIncrement(int volatile* addend) { return OSAtomicIncrement32Barrier(const_cast<int*>(addend)); } inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Barrier(const_cast<int*>(addend)); } @@ -100,7 +100,7 @@ inline int atomicIncrement(int volatile* addend) { return android_atomic_inc(add inline int atomicDecrement(int volatile* addend) { return android_atomic_dec(addend); } #elif COMPILER(GCC) && !CPU(SPARC64) && !OS(SYMBIAN) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc -#define WTF_USE_LOCKFREE_THREADSAFESHARED 1 +#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1 inline int atomicIncrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, 1) + 1; } inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, -1) - 1; } @@ -109,7 +109,7 @@ inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_ } // namespace WTF -#if USE(LOCKFREE_THREADSAFESHARED) +#if USE(LOCKFREE_THREADSAFEREFCOUNTED) using WTF::atomicDecrement; using WTF::atomicIncrement; #endif diff --git a/Source/JavaScriptCore/wtf/CMakeLists.txt b/Source/JavaScriptCore/wtf/CMakeLists.txt index c27b2e5..304be73 100644 --- a/Source/JavaScriptCore/wtf/CMakeLists.txt +++ b/Source/JavaScriptCore/wtf/CMakeLists.txt @@ -30,6 +30,7 @@ SET(WTF_HEADERS HashSet.h HashTable.h HashTraits.h + HexNumber.h ListHashSet.h ListRefPtr.h Locker.h @@ -76,7 +77,7 @@ SET(WTF_HEADERS TCSpinLock.h TCSystemAlloc.h ThreadIdentifierDataPthreads.h - ThreadSafeShared.h + ThreadSafeRefCounted.h ThreadSpecific.h Threading.h ThreadingPrimitives.h diff --git a/Source/JavaScriptCore/wtf/CrossThreadRefCounted.h b/Source/JavaScriptCore/wtf/CrossThreadRefCounted.h index 8b65977..9d093ee 100644 --- a/Source/JavaScriptCore/wtf/CrossThreadRefCounted.h +++ b/Source/JavaScriptCore/wtf/CrossThreadRefCounted.h @@ -38,10 +38,10 @@ namespace WTF { - // Used to allowing sharing data across classes and threads (like ThreadedSafeShared). + // Used to allowing sharing data across classes and threads (like ThreadSafeRefCounted). // - // Why not just use ThreadSafeShared? - // ThreadSafeShared can have a significant perf impact when used in low level classes + // Why not just use ThreadSafeRefCounted? + // ThreadSafeRefCounted can have a significant perf impact when used in low level classes // (like UString) that get ref/deref'ed a lot. This class has the benefit of doing fast ref // counts like RefPtr whenever possible, but it has the downside that you need to copy it // to use it on another thread. @@ -72,7 +72,7 @@ namespace WTF { } private: - CrossThreadRefCounted(T* data, ThreadSafeSharedBase* threadedCounter) + CrossThreadRefCounted(T* data, ThreadSafeRefCountedBase* threadedCounter) : m_threadSafeRefCounter(threadedCounter) , m_data(data) #ifndef NDEBUG @@ -97,7 +97,7 @@ namespace WTF { #endif RefCountedBase m_refCounter; - ThreadSafeSharedBase* m_threadSafeRefCounter; + ThreadSafeRefCountedBase* m_threadSafeRefCounter; T* m_data; #ifndef NDEBUG ThreadIdentifier m_threadId; @@ -154,7 +154,7 @@ namespace WTF { if (m_threadSafeRefCounter) m_threadSafeRefCounter->ref(); else - m_threadSafeRefCounter = new ThreadSafeSharedBase(2); + m_threadSafeRefCounter = new ThreadSafeRefCountedBase(2); return adoptRef(new CrossThreadRefCounted<T>(m_data, m_threadSafeRefCounter)); } diff --git a/Source/JavaScriptCore/wtf/DateMath.cpp b/Source/JavaScriptCore/wtf/DateMath.cpp index 062cc1b..70c0cf4 100644 --- a/Source/JavaScriptCore/wtf/DateMath.cpp +++ b/Source/JavaScriptCore/wtf/DateMath.cpp @@ -75,6 +75,9 @@ #include "Assertions.h" #include "ASCIICType.h" #include "CurrentTime.h" +#if USE(JSC) +#include "JSObject.h" +#endif #include "MathExtras.h" #if USE(JSC) #include "ScopeChain.h" @@ -924,8 +927,10 @@ static double parseDateFromNullTerminatedCharacters(const char* dateString, bool } } - // The year may be after the time but before the time zone. - if (year <= 0) { + // The year may be after the time but before the time zone, but don't + // confuse a time zone specificed as an offset from UTC (e.g. +0100) with a + // four-digit year. + if (year <= 0 && *dateString != '+' && *dateString != '-') { if (!parseLong(dateString, &newPosStr, 10, &year)) year = 0; dateString = newPosStr; diff --git a/Source/JavaScriptCore/wtf/ExportMacros.h b/Source/JavaScriptCore/wtf/ExportMacros.h new file mode 100644 index 0000000..3fadd37 --- /dev/null +++ b/Source/JavaScriptCore/wtf/ExportMacros.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file handles shared library symbol export decorations. It is recommended + * that all WebKit projects use these definitions so that symbol exports work + * properly on all platforms and compilers that WebKit builds under. + */ + +#ifndef ExportMacros_h +#define ExportMacros_h + +#include "Platform.h" + +#if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !COMPILER(GCC) +#define WTF_EXPORT __declspec(dllexport) +#define WTF_IMPORT __declspec(dllimport) +#elif defined(__GNUC__) && !defined(__CC_ARM) && !defined(__ARMCC__) +#define WTF_EXPORT __attribute__((visibility("default"))) +#define WTF_IMPORT WTF_EXPORT +#else +#define WTF_EXPORT +#define WTF_IMPORT +#endif + +#endif /* ExportMacros_h */ diff --git a/Source/JavaScriptCore/wtf/HexNumber.h b/Source/JavaScriptCore/wtf/HexNumber.h new file mode 100644 index 0000000..8fd6032 --- /dev/null +++ b/Source/JavaScriptCore/wtf/HexNumber.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2011 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef HexNumber_h +#define HexNumber_h + +#include <wtf/text/StringConcatenate.h> + +namespace WTF { + +enum HexConversionMode { + Lowercase, + Uppercase +}; + +namespace Internal { + +static const char* hexDigitsForMode(HexConversionMode mode) +{ + static const char lowerHexDigits[17] = "0123456789abcdef"; + static const char upperHexDigits[17] = "0123456789ABCDEF"; + return mode == Lowercase ? lowerHexDigits : upperHexDigits; +} + +}; // namespace Internal + +template<typename T> +inline void appendByteAsHex(unsigned char byte, T& destination, HexConversionMode mode = Uppercase) +{ + const char* hexDigits = Internal::hexDigitsForMode(mode); + destination.append(hexDigits[byte >> 4]); + destination.append(hexDigits[byte & 0xF]); +} + +template<typename T> +inline void placeByteAsHexCompressIfPossible(unsigned char byte, T& destination, unsigned& index, HexConversionMode mode = Uppercase) +{ + const char* hexDigits = Internal::hexDigitsForMode(mode); + if (byte >= 0x10) + destination[index++] = hexDigits[byte >> 4]; + destination[index++] = hexDigits[byte & 0xF]; +} + +template<typename T> +inline void placeByteAsHex(unsigned char byte, T& destination, HexConversionMode mode = Uppercase) +{ + const char* hexDigits = Internal::hexDigitsForMode(mode); + *destination++ = hexDigits[byte >> 4]; + *destination++ = hexDigits[byte & 0xF]; +} + +template<typename T> +inline void appendUnsignedAsHex(unsigned number, T& destination, HexConversionMode mode = Uppercase) +{ + const char* hexDigits = Internal::hexDigitsForMode(mode); + Vector<UChar, 8> result; + do { + result.prepend(hexDigits[number % 16]); + number >>= 4; + } while (number > 0); + + destination.append(result.data(), result.size()); +} + +// Same as appendUnsignedAsHex, but using exactly 'desiredDigits' for the conversion. +template<typename T> +inline void appendUnsignedAsHexFixedSize(unsigned number, T& destination, unsigned desiredDigits, HexConversionMode mode = Uppercase) +{ + ASSERT(desiredDigits); + + const char* hexDigits = Internal::hexDigitsForMode(mode); + Vector<UChar, 8> result; + do { + result.prepend(hexDigits[number % 16]); + number >>= 4; + } while (result.size() < desiredDigits); + + ASSERT(result.size() == desiredDigits); + destination.append(result.data(), result.size()); +} + +} // namespace WTF + +using WTF::appendByteAsHex; +using WTF::appendUnsignedAsHex; +using WTF::appendUnsignedAsHexFixedSize; +using WTF::placeByteAsHex; +using WTF::placeByteAsHexCompressIfPossible; +using WTF::Lowercase; + +#endif // HexNumber_h diff --git a/Source/JavaScriptCore/wtf/MathExtras.h b/Source/JavaScriptCore/wtf/MathExtras.h index ec27f5f..66e557f 100644 --- a/Source/JavaScriptCore/wtf/MathExtras.h +++ b/Source/JavaScriptCore/wtf/MathExtras.h @@ -90,7 +90,7 @@ inline bool isfinite(double x) { return finite(x) && !isnand(x); } inline bool isinf(double x) { return !finite(x) && !isnand(x); } #endif #ifndef signbit -inline bool signbit(double x) { return x < 0.0; } // FIXME: Wrong for negative 0. +inline bool signbit(double x) { return copysign(1.0, x) < 0; } #endif #endif @@ -106,7 +106,7 @@ inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x #endif -#if COMPILER(MSVC) || COMPILER(RVCT) +#if COMPILER(MSVC) || (COMPILER(RVCT) && !(RVCT_VERSION_AT_LEAST(3, 0, 0, 0))) // We must not do 'num + 0.5' or 'num - 0.5' because they can cause precision loss. static double round(double num) @@ -233,7 +233,12 @@ inline int clampToPositiveInteger(float d) return static_cast<int>(std::max<float>(std::min(d, maxIntAsFloat), 0)); } -#if !COMPILER(MSVC) && !COMPILER(WINSCW) && !(COMPILER(RVCT) && (OS(SYMBIAN) || PLATFORM(BREWMP))) +inline int clampToInteger(unsigned value) +{ + return static_cast<int>(std::min(value, static_cast<unsigned>(std::numeric_limits<int>::max()))); +} + +#if !COMPILER(MSVC) && !COMPILER(WINSCW) && !(COMPILER(RVCT) && (OS(SYMBIAN) || PLATFORM(BREWMP))) && !OS(SOLARIS) using std::isfinite; using std::isinf; using std::isnan; diff --git a/Source/JavaScriptCore/wtf/MessageQueue.h b/Source/JavaScriptCore/wtf/MessageQueue.h index 7c18a0c..2b774fb 100644 --- a/Source/JavaScriptCore/wtf/MessageQueue.h +++ b/Source/JavaScriptCore/wtf/MessageQueue.h @@ -41,7 +41,7 @@ namespace WTF { enum MessageQueueWaitResult { MessageQueueTerminated, // Queue was destroyed while waiting for message. MessageQueueTimeout, // Timeout was specified and it expired. - MessageQueueMessageReceived, // A message was successfully received and returned. + MessageQueueMessageReceived // A message was successfully received and returned. }; // The queue takes ownership of messages and transfer it to the new owner diff --git a/Source/JavaScriptCore/wtf/Platform.h b/Source/JavaScriptCore/wtf/Platform.h index f4fdbcb..aee03e6 100644 --- a/Source/JavaScriptCore/wtf/Platform.h +++ b/Source/JavaScriptCore/wtf/Platform.h @@ -114,6 +114,11 @@ #define WTF_COMPILER_INTEL 1 #endif +/* COMPILER(SUNCC) */ +#if defined(__SUNPRO_CC) || defined(__SUNPRO_C) +#define WTF_COMPILER_SUNCC 1 +#endif + /* ==== CPU() - the target CPU architecture ==== */ /* This also defines CPU(BIG_ENDIAN) or CPU(MIDDLE_ENDIAN) or neither, as appropriate. */ @@ -565,7 +570,11 @@ #define WTF_USE_MERSENNE_TWISTER_19937 1 #endif -#if (PLATFORM(GTK) || PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(WIN) || (PLATFORM(QT) && OS(DARWIN) && !ENABLE(SINGLE_THREADED))) && !defined(ENABLE_JSC_MULTIPLE_THREADS) +#if PLATFORM(QT) && OS(UNIX) && !OS(SYMBIAN) && !OS(DARWIN) +#define WTF_USE_PTHREAD_BASED_QT 1 +#endif + +#if (PLATFORM(GTK) || PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(WIN) || (PLATFORM(QT) && (OS(DARWIN) || USE(PTHREAD_BASED_QT)) && !ENABLE(SINGLE_THREADED))) && !defined(ENABLE_JSC_MULTIPLE_THREADS) #define ENABLE_JSC_MULTIPLE_THREADS 1 #endif @@ -598,10 +607,6 @@ #define WTF_USE_ICU_UNICODE 1 #endif -#if !PLATFORM(CHROMIUM) /* Chromium controls this macro with a gyp define */ -#define WTF_USE_BUILTIN_UTF8_CODEC 1 -#endif - #if PLATFORM(MAC) && !PLATFORM(IOS) #if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_TIGER) && CPU(X86_64) #define WTF_USE_PLUGIN_HOST_PROCESS 1 @@ -963,6 +968,10 @@ #define ENABLE_GEOLOCATION 0 #endif +#if !defined(ENABLE_GESTURE_RECOGNIZER) +#define ENABLE_GESTURE_RECOGNIZER 0 +#endif + #if !defined(ENABLE_NOTIFICATIONS) #define ENABLE_NOTIFICATIONS 0 #endif @@ -1022,6 +1031,13 @@ #define ENABLE_JIT 1 #endif +/* Currently only implemented for JSVALUE64, only tested on PLATFORM(MAC) */ +#if ENABLE(JIT) && USE(JSVALUE64) && PLATFORM(MAC) +#define ENABLE_DFG_JIT 1 +/* Enabled with restrictions to circumvent known performance regressions. */ +#define ENABLE_DFG_JIT_RESTRICTIONS 1 +#endif + /* Ensure that either the JIT or the interpreter has been enabled. */ #if !defined(ENABLE_INTERPRETER) && !ENABLE(JIT) #define ENABLE_INTERPRETER 1 @@ -1145,6 +1161,10 @@ #define WTF_USE_PROTECTION_SPACE_AUTH_CALLBACK 1 #endif +#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#define WTF_USE_AVFOUNDATION 1 +#endif + #if COMPILER(GCC) #define WARN_UNUSED_RETURN __attribute__ ((warn_unused_result)) #else @@ -1184,4 +1204,10 @@ #include "GTypedefs.h" #endif +/* FIXME: This define won't be needed once #27551 is fully landed. However, + since most ports try to support sub-project independence, adding new headers + to WTF causes many ports to break, and so this way we can address the build + breakages one port at a time. */ +#define WTF_USE_EXPORT_MACROS 0 + #endif /* WTF_Platform_h */ diff --git a/Source/JavaScriptCore/wtf/RefCounted.h b/Source/JavaScriptCore/wtf/RefCounted.h index da178b2..12b670e 100644 --- a/Source/JavaScriptCore/wtf/RefCounted.h +++ b/Source/JavaScriptCore/wtf/RefCounted.h @@ -59,6 +59,12 @@ public: #endif } + // Helper for generating JIT code. Please do not use for non-JIT purposes. + const int* addressOfCount() const + { + return &m_refCount; + } + protected: RefCountedBase() : m_refCount(1) @@ -93,12 +99,6 @@ protected: return false; } - // Helper for generating JIT code. Please do not use for non-JIT purposes. - int* addressOfCount() - { - return &m_refCount; - } - #ifndef NDEBUG bool deletionHasBegun() const { diff --git a/Source/JavaScriptCore/wtf/StdLibExtras.h b/Source/JavaScriptCore/wtf/StdLibExtras.h index 4bb0076..0dacb91 100644 --- a/Source/JavaScriptCore/wtf/StdLibExtras.h +++ b/Source/JavaScriptCore/wtf/StdLibExtras.h @@ -114,6 +114,53 @@ inline size_t bitCount(unsigned bits) template<typename T, size_t Size> char (&ArrayLengthHelperFunction(T (&)[Size]))[Size]; #define WTF_ARRAY_LENGTH(array) sizeof(::WTF::ArrayLengthHelperFunction(array)) +// Efficient implementation that takes advantage of powers of two. +template<size_t divisor> inline size_t roundUpToMultipleOf(size_t x) +{ + COMPILE_ASSERT(divisor && !(divisor & (divisor - 1)), divisor_is_a_power_of_two); + + size_t remainderMask = divisor - 1; + return (x + remainderMask) & ~remainderMask; +} + +// Binary search algorithm, calls extractKey on pre-sorted elements in array, +// compares result with key (KeyTypes should be comparable with '--', '<', '>'). +// Optimized for cases where the array contains the key, checked by assertions. +template<typename ArrayType, typename KeyType, KeyType(*extractKey)(ArrayType*)> +inline ArrayType* binarySearch(ArrayType* array, size_t size, KeyType key) +{ + // The array must contain at least one element (pre-condition, array does conatin key). + // If the array only contains one element, no need to do the comparison. + while (size > 1) { + // Pick an element to check, half way through the array, and read the value. + int pos = (size - 1) >> 1; + KeyType val = extractKey(&array[pos]); + + // If the key matches, success! + if (val == key) + return &array[pos]; + // The item we are looking for is smaller than the item being check; reduce the value of 'size', + // chopping off the right hand half of the array. + else if (key < val) + size = pos; + // Discard all values in the left hand half of the array, up to and including the item at pos. + else { + size -= (pos + 1); + array += (pos + 1); + } + + // 'size' should never reach zero. + ASSERT(size); + } + + // If we reach this point we've chopped down to one element, no need to check it matches + ASSERT(size == 1); + ASSERT(key == extractKey(&array[0])); + return &array[0]; +} + } // namespace WTF +using WTF::binarySearch; + #endif // WTF_StdLibExtras_h diff --git a/Source/JavaScriptCore/wtf/StringHasher.h b/Source/JavaScriptCore/wtf/StringHasher.h index a84b2c4..5a2c36c 100644 --- a/Source/JavaScriptCore/wtf/StringHasher.h +++ b/Source/JavaScriptCore/wtf/StringHasher.h @@ -88,7 +88,7 @@ public: return result; } - template<typename T, UChar Converter(T)> static inline unsigned createHash(const T* data, unsigned length) + template<typename T, UChar Converter(T)> static inline unsigned computeHash(const T* data, unsigned length) { StringHasher hasher; bool rem = length & 1; @@ -105,7 +105,7 @@ public: return hasher.hash(); } - template<typename T, UChar Converter(T)> static inline unsigned createHash(const T* data) + template<typename T, UChar Converter(T)> static inline unsigned computeHash(const T* data) { StringHasher hasher; @@ -125,26 +125,26 @@ public: return hasher.hash(); } - template<typename T> static inline unsigned createHash(const T* data, unsigned length) + template<typename T> static inline unsigned computeHash(const T* data, unsigned length) { - return createHash<T, defaultCoverter>(data, length); + return computeHash<T, defaultCoverter>(data, length); } - template<typename T> static inline unsigned createHash(const T* data) + template<typename T> static inline unsigned computeHash(const T* data) { - return createHash<T, defaultCoverter>(data); + return computeHash<T, defaultCoverter>(data); } - template<size_t length> static inline unsigned createBlobHash(const void* data) + template<size_t length> static inline unsigned hashMemory(const void* data) { COMPILE_ASSERT(!(length % 4), length_must_be_a_multible_of_four); - return createHash<UChar>(static_cast<const UChar*>(data), length / sizeof(UChar)); + return computeHash<UChar>(static_cast<const UChar*>(data), length / sizeof(UChar)); } - static inline unsigned createBlobHash(const void* data, unsigned size) + static inline unsigned hashMemory(const void* data, unsigned size) { ASSERT(!(size % 2)); - return createHash<UChar>(static_cast<const UChar*>(data), size / sizeof(UChar)); + return computeHash<UChar>(static_cast<const UChar*>(data), size / sizeof(UChar)); } private: @@ -173,4 +173,6 @@ private: } // namespace WTF +using WTF::StringHasher; + #endif // WTF_StringHasher_h diff --git a/Source/JavaScriptCore/wtf/ThreadSafeShared.h b/Source/JavaScriptCore/wtf/ThreadSafeRefCounted.h index a6a1cf2..c9beec4 100644 --- a/Source/JavaScriptCore/wtf/ThreadSafeShared.h +++ b/Source/JavaScriptCore/wtf/ThreadSafeRefCounted.h @@ -56,8 +56,8 @@ * DEALINGS IN THE SOFTWARE. */ -#ifndef ThreadSafeShared_h -#define ThreadSafeShared_h +#ifndef ThreadSafeRefCounted_h +#define ThreadSafeRefCounted_h #include "Platform.h" @@ -66,17 +66,18 @@ namespace WTF { -class ThreadSafeSharedBase { - WTF_MAKE_NONCOPYABLE(ThreadSafeSharedBase); WTF_MAKE_FAST_ALLOCATED; +class ThreadSafeRefCountedBase { + WTF_MAKE_NONCOPYABLE(ThreadSafeRefCountedBase); + WTF_MAKE_FAST_ALLOCATED; public: - ThreadSafeSharedBase(int initialRefCount = 1) + ThreadSafeRefCountedBase(int initialRefCount = 1) : m_refCount(initialRefCount) { } void ref() { -#if USE(LOCKFREE_THREADSAFESHARED) +#if USE(LOCKFREE_THREADSAFEREFCOUNTED) atomicIncrement(&m_refCount); #else MutexLocker locker(m_mutex); @@ -91,7 +92,7 @@ public: int refCount() const { -#if !USE(LOCKFREE_THREADSAFESHARED) +#if !USE(LOCKFREE_THREADSAFEREFCOUNTED) MutexLocker locker(m_mutex); #endif return static_cast<int const volatile &>(m_refCount); @@ -101,7 +102,7 @@ protected: // Returns whether the pointer should be freed or not. bool derefBase() { -#if USE(LOCKFREE_THREADSAFESHARED) +#if USE(LOCKFREE_THREADSAFEREFCOUNTED) if (atomicDecrement(&m_refCount) <= 0) return true; #else @@ -122,12 +123,12 @@ private: friend class CrossThreadRefCounted; int m_refCount; -#if !USE(LOCKFREE_THREADSAFESHARED) +#if !USE(LOCKFREE_THREADSAFEREFCOUNTED) mutable Mutex m_mutex; #endif }; -template<class T> class ThreadSafeShared : public ThreadSafeSharedBase { +template<class T> class ThreadSafeRefCounted : public ThreadSafeRefCountedBase { public: void deref() { @@ -136,13 +137,13 @@ public: } protected: - ThreadSafeShared() + ThreadSafeRefCounted() { } }; } // namespace WTF -using WTF::ThreadSafeShared; +using WTF::ThreadSafeRefCounted; -#endif // ThreadSafeShared_h +#endif // ThreadSafeRefCounted_h diff --git a/Source/JavaScriptCore/wtf/Threading.h b/Source/JavaScriptCore/wtf/Threading.h index 044365f..b6f8c24 100644 --- a/Source/JavaScriptCore/wtf/Threading.h +++ b/Source/JavaScriptCore/wtf/Threading.h @@ -67,7 +67,7 @@ #include <wtf/Locker.h> #include <wtf/MainThread.h> #include <wtf/Noncopyable.h> -#include <wtf/ThreadSafeShared.h> +#include <wtf/ThreadSafeRefCounted.h> #include <wtf/ThreadingPrimitives.h> // For portability, we do not use thread-safe statics natively supported by some compilers (e.g. gcc). diff --git a/Source/JavaScriptCore/wtf/ThreadingPthreads.cpp b/Source/JavaScriptCore/wtf/ThreadingPthreads.cpp index aa63f33..0ffcfe2 100644 --- a/Source/JavaScriptCore/wtf/ThreadingPthreads.cpp +++ b/Source/JavaScriptCore/wtf/ThreadingPthreads.cpp @@ -55,6 +55,10 @@ #include <wtf/PassOwnPtr.h> #endif +#if OS(MAC_OS_X) && !defined(BUILDING_ON_LEOPARD) +#include <objc/objc-auto.h> +#endif + namespace WTF { typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap; @@ -190,6 +194,12 @@ void initializeCurrentThreadInternal(const char* threadName) UNUSED_PARAM(threadName); #endif +#if OS(MAC_OS_X) && !defined(BUILDING_ON_LEOPARD) + // All threads that potentially use APIs above the BSD layer must be registered with the Objective-C + // garbage collector in case API implementations use garbage-collected memory. + objc_registerThreadWithCollector(); +#endif + ThreadIdentifier id = identifierByPthreadHandle(pthread_self()); ASSERT(id); ThreadIdentifierData::initialize(id); diff --git a/Source/JavaScriptCore/wtf/Vector.h b/Source/JavaScriptCore/wtf/Vector.h index 2fb4114..b26857c 100644 --- a/Source/JavaScriptCore/wtf/Vector.h +++ b/Source/JavaScriptCore/wtf/Vector.h @@ -40,7 +40,7 @@ namespace WTF { using std::max; // WTF_ALIGN_OF / WTF_ALIGNED - #if COMPILER(GCC) || COMPILER(MINGW) || COMPILER(RVCT) || COMPILER(WINSCW) + #if COMPILER(GCC) || COMPILER(MINGW) || COMPILER(RVCT) || COMPILER(WINSCW) || COMPILER(SUNCC) #define WTF_ALIGN_OF(type) __alignof__(type) #define WTF_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((__aligned__(n))) #elif COMPILER(MSVC) @@ -566,6 +566,7 @@ namespace WTF { T& last() { return at(size() - 1); } const T& last() const { return at(size() - 1); } + template<typename U> bool contains(const U&) const; template<typename U> size_t find(const U&) const; template<typename U> size_t reverseFind(const U&) const; @@ -745,6 +746,13 @@ namespace WTF { template<typename T, size_t inlineCapacity> template<typename U> + bool Vector<T, inlineCapacity>::contains(const U& value) const + { + return find(value) != notFound; + } + + template<typename T, size_t inlineCapacity> + template<typename U> size_t Vector<T, inlineCapacity>::find(const U& value) const { for (size_t i = 0; i < size(); ++i) { diff --git a/Source/JavaScriptCore/wtf/text/AtomicString.cpp b/Source/JavaScriptCore/wtf/text/AtomicString.cpp index e0a866d..eb0dbbb 100644 --- a/Source/JavaScriptCore/wtf/text/AtomicString.cpp +++ b/Source/JavaScriptCore/wtf/text/AtomicString.cpp @@ -87,7 +87,7 @@ static inline PassRefPtr<StringImpl> addToStringTable(const T& value) struct CStringTranslator { static unsigned hash(const char* c) { - return StringImpl::computeHash(c); + return StringHasher::computeHash(c); } static bool equal(StringImpl* r, const char* s) @@ -142,7 +142,7 @@ static inline bool equal(StringImpl* string, const UChar* characters, unsigned l // FIXME: perhaps we should have a more abstract macro that indicates when // going 4 bytes at a time is unsafe -#if CPU(ARM) || CPU(SH4) || CPU(MIPS) +#if CPU(ARM) || CPU(SH4) || CPU(MIPS) || CPU(SPARC) const UChar* stringCharacters = string->characters(); for (unsigned i = 0; i != length; ++i) { if (*stringCharacters++ != *characters++) @@ -176,7 +176,7 @@ bool operator==(const AtomicString& string, const Vector<UChar>& vector) struct UCharBufferTranslator { static unsigned hash(const UCharBuffer& buf) { - return StringImpl::computeHash(buf.s, buf.length); + return StringHasher::computeHash(buf.s, buf.length); } static bool equal(StringImpl* const& str, const UCharBuffer& buf) @@ -201,7 +201,7 @@ struct HashAndCharacters { struct HashAndCharactersTranslator { static unsigned hash(const HashAndCharacters& buffer) { - ASSERT(buffer.hash == StringImpl::computeHash(buffer.characters, buffer.length)); + ASSERT(buffer.hash == StringHasher::computeHash(buffer.characters, buffer.length)); return buffer.hash; } diff --git a/Source/JavaScriptCore/wtf/text/StringConcatenate.h b/Source/JavaScriptCore/wtf/text/StringConcatenate.h index 92a2d06..7fa7d2c 100644 --- a/Source/JavaScriptCore/wtf/text/StringConcatenate.h +++ b/Source/JavaScriptCore/wtf/text/StringConcatenate.h @@ -89,6 +89,34 @@ private: }; template<> +class StringTypeAdapter<const UChar*> { +public: + StringTypeAdapter<const UChar*>(const UChar* buffer) + : m_buffer(buffer) + { + size_t len = 0; + while (m_buffer[len] != UChar(0)) + len++; + + if (len > std::numeric_limits<unsigned>::max()) + CRASH(); + + m_length = len; + } + + unsigned length() { return m_length; } + + void writeTo(UChar* destination) + { + memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(UChar)); + } + +private: + const UChar* m_buffer; + unsigned m_length; +}; + +template<> class StringTypeAdapter<const char*> { public: StringTypeAdapter<const char*>(const char* buffer) diff --git a/Source/JavaScriptCore/wtf/text/StringHash.h b/Source/JavaScriptCore/wtf/text/StringHash.h index d7aabdb..80193a6 100644 --- a/Source/JavaScriptCore/wtf/text/StringHash.h +++ b/Source/JavaScriptCore/wtf/text/StringHash.h @@ -104,7 +104,7 @@ namespace WTF { static unsigned hash(const UChar* data, unsigned length) { - return StringHasher::createHash<UChar, foldCase<UChar> >(data, length); + return StringHasher::computeHash<UChar, foldCase<UChar> >(data, length); } static unsigned hash(StringImpl* str) @@ -114,7 +114,7 @@ namespace WTF { static unsigned hash(const char* data, unsigned length) { - return StringHasher::createHash<char, foldCase<char> >(data, length); + return StringHasher::computeHash<char, foldCase<char> >(data, length); } static bool equal(const StringImpl* a, const StringImpl* b) diff --git a/Source/JavaScriptCore/wtf/text/StringImpl.h b/Source/JavaScriptCore/wtf/text/StringImpl.h index a08427b..81911b3 100644 --- a/Source/JavaScriptCore/wtf/text/StringImpl.h +++ b/Source/JavaScriptCore/wtf/text/StringImpl.h @@ -136,7 +136,7 @@ private: { ASSERT(!isStatic()); ASSERT(!m_hash); - ASSERT(hash == computeHash(m_data, m_length)); + ASSERT(hash == StringHasher::computeHash(m_data, m_length)); m_hash = hash; } @@ -235,11 +235,8 @@ public: m_refCountAndFlags &= ~s_refCountFlagIsAtomic; } - unsigned hash() const { if (!m_hash) m_hash = computeHash(m_data, m_length); return m_hash; } + unsigned hash() const { if (!m_hash) m_hash = StringHasher::computeHash(m_data, m_length); return m_hash; } unsigned existingHash() const { ASSERT(m_hash); return m_hash; } - static unsigned computeHash(const UChar* data, unsigned length) { return WTF::StringHasher::createHash<UChar>(data, length); } - static unsigned computeHash(const char* data, unsigned length) { return WTF::StringHasher::createHash<char>(data, length); } - static unsigned computeHash(const char* data) { return WTF::StringHasher::createHash<char>(data); } ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic))) delete this; } ALWAYS_INLINE bool hasOneRef() const { return (m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic)) == s_refCountIncrement; } diff --git a/Source/JavaScriptCore/wtf/unicode/UTF8.cpp b/Source/JavaScriptCore/wtf/unicode/UTF8.cpp index 4c3738b..6981fe4 100644 --- a/Source/JavaScriptCore/wtf/unicode/UTF8.cpp +++ b/Source/JavaScriptCore/wtf/unicode/UTF8.cpp @@ -319,7 +319,7 @@ static inline unsigned calculateStringHashAndLengthFromUTF8Internal(const char* if (!data) return 0; - WTF::StringHasher stringHasher; + StringHasher stringHasher; dataLength = 0; utf16Length = 0; diff --git a/Source/JavaScriptCore/yarr/YarrInterpreter.cpp b/Source/JavaScriptCore/yarr/YarrInterpreter.cpp index 37d44f7..d8c5d27 100644 --- a/Source/JavaScriptCore/yarr/YarrInterpreter.cpp +++ b/Source/JavaScriptCore/yarr/YarrInterpreter.cpp @@ -1234,6 +1234,10 @@ public: if (input.checkInput(currentTerm().checkInputCount)) MATCH_NEXT(); BACKTRACK(); + + case ByteTerm::TypeUncheckInput: + input.uncheckInput(currentTerm().checkInputCount); + MATCH_NEXT(); } // We should never fall-through to here. @@ -1354,6 +1358,10 @@ public: case ByteTerm::TypeCheckInput: input.uncheckInput(currentTerm().checkInputCount); BACKTRACK(); + + case ByteTerm::TypeUncheckInput: + input.checkInput(currentTerm().checkInputCount); + BACKTRACK(); } ASSERT_NOT_REACHED(); @@ -1453,6 +1461,11 @@ public: m_bodyDisjunction->terms.append(ByteTerm::CheckInput(count)); } + void uncheckInput(unsigned count) + { + m_bodyDisjunction->terms.append(ByteTerm::UncheckInput(count)); + } + void assertionBOL(int inputPosition) { m_bodyDisjunction->terms.append(ByteTerm::BOL(inputPosition)); @@ -1849,10 +1862,21 @@ public: ASSERT(currentCountAlreadyChecked >= static_cast<unsigned>(term.inputPosition)); int positiveInputOffset = currentCountAlreadyChecked - term.inputPosition; + int uncheckAmount = positiveInputOffset - term.parentheses.disjunction->m_minimumSize; + + if (uncheckAmount > 0) { + uncheckInput(uncheckAmount); + currentCountAlreadyChecked -= uncheckAmount; + } else + uncheckAmount = 0; atomParentheticalAssertionBegin(term.parentheses.subpatternId, term.invert(), term.frameLocation, alternativeFrameLocation); emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, positiveInputOffset, true); atomParentheticalAssertionEnd(0, term.frameLocation, term.quantityCount, term.quantityType); + if (uncheckAmount) { + checkInput(uncheckAmount); + currentCountAlreadyChecked += uncheckAmount; + } break; } } diff --git a/Source/JavaScriptCore/yarr/YarrInterpreter.h b/Source/JavaScriptCore/yarr/YarrInterpreter.h index eea5266..a9f4d48 100644 --- a/Source/JavaScriptCore/yarr/YarrInterpreter.h +++ b/Source/JavaScriptCore/yarr/YarrInterpreter.h @@ -70,6 +70,7 @@ struct ByteTerm { TypeParentheticalAssertionBegin, TypeParentheticalAssertionEnd, TypeCheckInput, + TypeUncheckInput, } type; union { struct { @@ -205,6 +206,13 @@ struct ByteTerm { return term; } + static ByteTerm UncheckInput(unsigned count) + { + ByteTerm term(TypeUncheckInput); + term.checkInputCount = count; + return term; + } + static ByteTerm EOL(int inputPos) { ByteTerm term(TypeAssertionEOL); diff --git a/Source/JavaScriptCore/yarr/YarrJIT.cpp b/Source/JavaScriptCore/yarr/YarrJIT.cpp index e34e6f4..bc61a6e 100644 --- a/Source/JavaScriptCore/yarr/YarrJIT.cpp +++ b/Source/JavaScriptCore/yarr/YarrJIT.cpp @@ -157,7 +157,7 @@ class YarrGenerator : private MacroAssembler { } Jump unicodeFail; if (charClass->m_matchesUnicode.size() || charClass->m_rangesUnicode.size()) { - Jump isAscii = branch32(LessThanOrEqual, character, Imm32(0x7f)); + Jump isAscii = branch32(LessThanOrEqual, character, TrustedImm32(0x7f)); if (charClass->m_matchesUnicode.size()) { for (unsigned i = 0; i < charClass->m_matchesUnicode.size(); ++i) { @@ -207,9 +207,9 @@ class YarrGenerator : private MacroAssembler { } if (unsigned countAZaz = matchesAZaz.size()) { - or32(Imm32(32), character); + or32(TrustedImm32(32), character); for (unsigned i = 0; i < countAZaz; ++i) - matchDest.append(branch32(Equal, character, Imm32(matchesAZaz[i]))); + matchDest.append(branch32(Equal, character, TrustedImm32(matchesAZaz[i]))); } } @@ -265,14 +265,14 @@ class YarrGenerator : private MacroAssembler { poke(reg, frameLocation); } - void storeToFrame(Imm32 imm, unsigned frameLocation) + void storeToFrame(TrustedImm32 imm, unsigned frameLocation) { poke(imm, frameLocation); } DataLabelPtr storeToFrameWithPatch(unsigned frameLocation) { - return storePtrWithPatch(ImmPtr(0), Address(stackPointerRegister, frameLocation * sizeof(void*))); + return storePtrWithPatch(TrustedImmPtr(0), Address(stackPointerRegister, frameLocation * sizeof(void*))); } void loadFromFrame(unsigned frameLocation, RegisterID reg) @@ -1109,11 +1109,11 @@ class YarrGenerator : private MacroAssembler { if (m_term.quantityType == QuantifierGreedy) { // If this is -1 we have now tested with both with and without the parens. generator->loadFromFrame(parenthesesFrameLocation, indexTemporary); - m_backtrack.jumpToBacktrack(generator, generator->branch32(Equal, indexTemporary, Imm32(-1))); + m_backtrack.jumpToBacktrack(generator, generator->branch32(Equal, indexTemporary, TrustedImm32(-1))); } else if (m_term.quantityType == QuantifierNonGreedy) { // If this is -1 we have now tested with both with and without the parens. generator->loadFromFrame(parenthesesFrameLocation, indexTemporary); - generator->branch32(Equal, indexTemporary, Imm32(-1)).linkTo(m_nonGreedyTryParentheses, generator); + generator->branch32(Equal, indexTemporary, TrustedImm32(-1)).linkTo(m_nonGreedyTryParentheses, generator); } if (!m_doDirectBacktrack) @@ -1126,10 +1126,10 @@ class YarrGenerator : private MacroAssembler { m_withinBacktrackJumps.link(generator); if (m_term.capture()) - generator->store32(Imm32(-1), Address(output, (m_term.parentheses.subpatternId << 1) * sizeof(int))); + generator->store32(TrustedImm32(-1), Address(output, (m_term.parentheses.subpatternId << 1) * sizeof(int))); if (m_term.quantityType == QuantifierGreedy) { - generator->storeToFrame(Imm32(-1), parenthesesFrameLocation); + generator->storeToFrame(TrustedImm32(-1), parenthesesFrameLocation); generator->jump().linkTo(m_fallThrough, generator); nextBacktrackFallThrough = false; } else if (!nextBacktrackFallThrough) @@ -1271,7 +1271,7 @@ class YarrGenerator : private MacroAssembler { if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) { readCharacter(state.inputOffset(), character); - or32(Imm32(32), character); + or32(TrustedImm32(32), character); state.jumpToBacktrack(this, branch32(NotEqual, character, Imm32(Unicode::toLower(ch)))); } else { ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch))); @@ -1316,13 +1316,13 @@ class YarrGenerator : private MacroAssembler { Label loop(this); if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) { load16(BaseIndex(input, countRegister, TimesTwo, (state.inputOffset() + term.quantityCount) * sizeof(UChar)), character); - or32(Imm32(32), character); + or32(TrustedImm32(32), character); state.jumpToBacktrack(this, branch32(NotEqual, character, Imm32(Unicode::toLower(ch)))); } else { ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch))); state.jumpToBacktrack(this, branch16(NotEqual, BaseIndex(input, countRegister, TimesTwo, (state.inputOffset() + term.quantityCount) * sizeof(UChar)), Imm32(ch))); } - add32(Imm32(1), countRegister); + add32(TrustedImm32(1), countRegister); branch32(NotEqual, countRegister, index).linkTo(loop, this); } @@ -1333,22 +1333,22 @@ class YarrGenerator : private MacroAssembler { PatternTerm& term = state.term(); UChar ch = term.patternCharacter; - move(Imm32(0), countRegister); + move(TrustedImm32(0), countRegister); JumpList failures; Label loop(this); failures.append(atEndOfInput()); if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) { readCharacter(state.inputOffset(), character); - or32(Imm32(32), character); + or32(TrustedImm32(32), character); failures.append(branch32(NotEqual, character, Imm32(Unicode::toLower(ch)))); } else { ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch))); failures.append(jumpIfCharNotEquals(ch, state.inputOffset())); } - add32(Imm32(1), countRegister); - add32(Imm32(1), index); + add32(TrustedImm32(1), countRegister); + add32(TrustedImm32(1), index); if (term.quantityCount != quantifyInfinite) { branch32(NotEqual, countRegister, Imm32(term.quantityCount)).linkTo(loop, this); failures.append(jump()); @@ -1358,8 +1358,8 @@ class YarrGenerator : private MacroAssembler { Label backtrackBegin(this); loadFromFrame(term.frameLocation, countRegister); state.jumpToBacktrack(this, branchTest32(Zero, countRegister)); - sub32(Imm32(1), countRegister); - sub32(Imm32(1), index); + sub32(TrustedImm32(1), countRegister); + sub32(TrustedImm32(1), index); failures.link(this); @@ -1375,7 +1375,7 @@ class YarrGenerator : private MacroAssembler { PatternTerm& term = state.term(); UChar ch = term.patternCharacter; - move(Imm32(0), countRegister); + move(TrustedImm32(0), countRegister); Jump firstTimeDoNothing = jump(); @@ -1391,15 +1391,15 @@ class YarrGenerator : private MacroAssembler { branch32(Equal, countRegister, Imm32(term.quantityCount), hardFail); if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) { readCharacter(state.inputOffset(), character); - or32(Imm32(32), character); + or32(TrustedImm32(32), character); branch32(NotEqual, character, Imm32(Unicode::toLower(ch))).linkTo(hardFail, this); } else { ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch))); jumpIfCharNotEquals(ch, state.inputOffset()).linkTo(hardFail, this); } - add32(Imm32(1), countRegister); - add32(Imm32(1), index); + add32(TrustedImm32(1), countRegister); + add32(TrustedImm32(1), index); firstTimeDoNothing.link(this); storeToFrame(countRegister, term.frameLocation); @@ -1445,7 +1445,7 @@ class YarrGenerator : private MacroAssembler { matchDest.link(this); } - add32(Imm32(1), countRegister); + add32(TrustedImm32(1), countRegister); branch32(NotEqual, countRegister, index).linkTo(loop, this); } @@ -1455,7 +1455,7 @@ class YarrGenerator : private MacroAssembler { const RegisterID countRegister = regT1; PatternTerm& term = state.term(); - move(Imm32(0), countRegister); + move(TrustedImm32(0), countRegister); JumpList failures; Label loop(this); @@ -1472,8 +1472,8 @@ class YarrGenerator : private MacroAssembler { matchDest.link(this); } - add32(Imm32(1), countRegister); - add32(Imm32(1), index); + add32(TrustedImm32(1), countRegister); + add32(TrustedImm32(1), index); if (term.quantityCount != quantifyInfinite) { branch32(NotEqual, countRegister, Imm32(term.quantityCount)).linkTo(loop, this); failures.append(jump()); @@ -1483,8 +1483,8 @@ class YarrGenerator : private MacroAssembler { Label backtrackBegin(this); loadFromFrame(term.frameLocation, countRegister); state.jumpToBacktrack(this, branchTest32(Zero, countRegister)); - sub32(Imm32(1), countRegister); - sub32(Imm32(1), index); + sub32(TrustedImm32(1), countRegister); + sub32(TrustedImm32(1), index); failures.link(this); @@ -1499,7 +1499,7 @@ class YarrGenerator : private MacroAssembler { const RegisterID countRegister = regT1; PatternTerm& term = state.term(); - move(Imm32(0), countRegister); + move(TrustedImm32(0), countRegister); Jump firstTimeDoNothing = jump(); @@ -1524,8 +1524,8 @@ class YarrGenerator : private MacroAssembler { matchDest.link(this); } - add32(Imm32(1), countRegister); - add32(Imm32(1), index); + add32(TrustedImm32(1), countRegister); + add32(TrustedImm32(1), index); firstTimeDoNothing.link(this); storeToFrame(countRegister, term.frameLocation); @@ -1669,7 +1669,7 @@ class YarrGenerator : private MacroAssembler { if (term.quantityType == QuantifierGreedy) storeToFrame(index, parenthesesFrameLocation); else if (term.quantityType == QuantifierNonGreedy) { - storeToFrame(Imm32(-1), parenthesesFrameLocation); + storeToFrame(TrustedImm32(-1), parenthesesFrameLocation); nonGreedySkipParentheses = jump(); nonGreedyTryParentheses = label(); storeToFrame(index, parenthesesFrameLocation); @@ -2140,7 +2140,7 @@ class YarrGenerator : private MacroAssembler { if (m_pattern.m_body->m_callFrameSize) addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister); - move(Imm32(-1), returnRegister); + move(TrustedImm32(-1), returnRegister); generateReturn(); |