WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
WRONG PATCH
blah.patch (text/plain), 102.66 KB, created by
Filip Pizlo
on 2015-02-23 21:19:14 PST
(
hide
)
Description:
WRONG PATCH
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2015-02-23 21:19:14 PST
Size:
102.66 KB
patch
obsolete
>Index: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >=================================================================== >--- Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (revision 180529) >+++ Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (working copy) >@@ -116,7 +116,7 @@ ParserError BytecodeGenerator::generate( > m_codeBlock->shrinkToFit(); > > if (m_codeBlock->symbolTable() && !m_codeBlock->vm()->typeProfiler()) >- m_codeBlock->setSymbolTable(m_codeBlock->symbolTable()->cloneCapturedNames(*m_codeBlock->vm())); >+ m_codeBlock->setSymbolTable(m_codeBlock->symbolTable()->cloneIgnoringStack(*m_codeBlock->vm())); > > if (m_expressionTooDeep) > return ParserError(ParserError::OutOfMemory); >@@ -124,17 +124,28 @@ ParserError BytecodeGenerator::generate( > } > > bool BytecodeGenerator::addVar( >- const Identifier& ident, ConstantMode constantMode, WatchMode watchMode, RegisterID*& r0) >+ const Identifier& ident, ConstantMode constantMode, VarKind varKind, WatchMode watchMode, >+ RegisterID*& r0) > { > ASSERT(static_cast<size_t>(m_codeBlock->m_numVars) == m_calleeRegisters.size()); > > ConcurrentJITLocker locker(symbolTable().m_lock); >- int index = virtualRegisterForLocal(m_calleeRegisters.size()).offset(); >- SymbolTableEntry newEntry(index, constantMode == IsConstant ? ReadOnly : 0); >+ VarOffset varOffset; >+ if (varKind == HeapVarKind) >+ varOffset = VarOffset(HeapOffset(m_numCapturedVariables++)); >+ else { >+ ASSERT(varKind == StackVarKind); >+ varOffset = VarOffset(virtualRegisterForLocal(m_calleeRegisters.size())); >+ } >+ SymbolTableEntry newEntry(varOffset, constantMode == IsConstant ? ReadOnly : 0); > SymbolTable::Map::AddResult result = symbolTable().add(locker, ident.impl(), newEntry); > > if (!result.isNewEntry) { >- r0 = ®isterFor(result.iterator->value.getIndex()); >+ RELEASE_ASSERT(varKind == result.iterator->value.varOffset().kind()); >+ if (varKind == HeapVarKind) >+ r0 = nullptr; >+ else >+ r0 = ®isterFor(result.iterator->value.varOffset()); > return false; > } > >@@ -144,7 +155,10 @@ bool BytecodeGenerator::addVar( > m_watchableVariables.append(ident); > } > >- r0 = addVar(); >+ if (varKind == HeapVarKind) >+ r0 = nullptr; >+ else >+ r0 = addVar(); > > ASSERT(watchMode == NotWatchable || static_cast<size_t>(m_codeBlock->m_numVars) == m_watchableVariables.size()); > >@@ -231,7 +245,6 @@ BytecodeGenerator::BytecodeGenerator(VM& > } > RegisterID* localArgumentsRegister = nullptr; > RegisterID* scratch = addVar(); >- m_symbolTable->setCaptureStart(virtualRegisterForLocal(m_codeBlock->m_numVars).offset()); > > if (functionNode->usesArguments() || codeBlock->usesEval()) { // May reify arguments object. > RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code. >Index: Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >=================================================================== >--- Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (revision 180529) >+++ Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (working copy) >@@ -613,15 +613,15 @@ namespace JSC { > > // Adds a var slot and maps it to the name ident in symbolTable(). > enum WatchMode { IsWatchable, NotWatchable }; >- RegisterID* addVar(const Identifier& ident, ConstantMode constantMode, WatchMode watchMode) >+ RegisterID* addVar(const Identifier& ident, ConstantMode constantMode, VarKind varKind, WatchMode watchMode) > { > RegisterID* local; >- addVar(ident, constantMode, watchMode, local); >+ addVar(ident, constantMode, varKind, watchMode, local); > return local; > } > > // Ditto. Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used. >- bool addVar(const Identifier&, ConstantMode, WatchMode, RegisterID*&); >+ bool addVar(const Identifier&, ConstantMode, VarKind, WatchMode, RegisterID*&); > > // Adds an anonymous var slot. To give this slot a name, add it to symbolTable(). > RegisterID* addVar() >@@ -774,6 +774,7 @@ namespace JSC { > Vector<Identifier, 16> m_watchableVariables; > SegmentedVector<RegisterID, 32> m_constantPoolRegisters; > SegmentedVector<RegisterID, 32> m_calleeRegisters; >+ unsigned m_numCapturedVariables; > SegmentedVector<RegisterID, 32> m_parameters; > SegmentedVector<Label, 32> m_labels; > LabelScopeStore m_labelScopes; >Index: Source/JavaScriptCore/heap/CopyToken.h >=================================================================== >--- Source/JavaScriptCore/heap/CopyToken.h (revision 180529) >+++ Source/JavaScriptCore/heap/CopyToken.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2013 Apple Inc. All rights reserved. >+ * Copyright (C) 2013, 2015 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -32,7 +32,7 @@ enum CopyToken { > ButterflyCopyToken, > TypedArrayVectorCopyToken, > MapBackingStoreCopyToken, >- ArgumentsSlowArgumentDataCopyToken >+ DirectArgumentsOverridesCopyToken > }; > > } // namespace JSC >Index: Source/JavaScriptCore/runtime/ArgumentsMode.h >=================================================================== >--- Source/JavaScriptCore/runtime/ArgumentsMode.h (revision 0) >+++ Source/JavaScriptCore/runtime/ArgumentsMode.h (working copy) >@@ -0,0 +1,39 @@ >+/* >+ * Copyright (C) 2015 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 ArgumentsMode_h >+#define ArgumentsMode_h >+ >+namespace JSC { >+ >+enum ArgumentsMode { >+ ClonedArgumentsCreationMode, >+ FakeArgumentValuesCreationMode >+}; >+ >+} // namespace JSC >+ >+#endif // ArgumentsMode_h >+ >Index: Source/JavaScriptCore/runtime/CapturedArgumentsOffset.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/CapturedArgumentsOffset.cpp (revision 0) >+++ Source/JavaScriptCore/runtime/CapturedArgumentsOffset.cpp (working copy) >@@ -0,0 +1,42 @@ >+/* >+ * Copyright (C) 2015 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 "CapturedArgumentsOffset.h" >+ >+namespace JSC { >+ >+void CapturedArgumentsOffset::dump(PrintStream& out) const >+{ >+ if (!*this) { >+ out.print("capturedArgumentInvalid"); >+ return; >+ } >+ >+ out.print("capturedArgument", offset()); >+} >+ >+} // namespace JSC >+ >Index: Source/JavaScriptCore/runtime/CapturedArgumentsOffset.h >=================================================================== >--- Source/JavaScriptCore/runtime/CapturedArgumentsOffset.h (revision 0) >+++ Source/JavaScriptCore/runtime/CapturedArgumentsOffset.h (working copy) >@@ -0,0 +1,53 @@ >+/* >+ * Copyright (C) 2015 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 CapturedArgumentsOffset_h >+#define CapturedArgumentsOffset_h >+ >+#include "GenericOffset.h" >+#include <wtf/PrintStream.h> >+ >+namespace JSC { >+ >+// This is an offset into the special arguments object, which captures the arguments to a >+// function. It only comes into play it the arguments aren't also lifted into the activation. >+// If they were then accesses to the arguments would resolve to a ScopeOffset and not a >+// CapturedArgumentsOffset. >+class CapturedArgumentsOffset : public GenericOffset<CapturedArgumentsOffset> { >+public: >+ CapturedArgumentsOffset() { } >+ >+ explicit CapturedArgumentsOffset(unsigned offset) >+ : GenericOffset(offset) >+ { >+ } >+ >+ void dump(PrintStream&) const; >+}; >+ >+} // namespace JSC >+ >+#endif // CapturedArgumentsOffset_h >+ >Index: Source/JavaScriptCore/runtime/DirectArguments.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/DirectArguments.cpp (revision 0) >+++ Source/JavaScriptCore/runtime/DirectArguments.cpp (working copy) >@@ -0,0 +1,269 @@ >+/* >+ * Copyright (C) 2015 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 "DirectArguments.h" >+ >+#include "JSArgumentsIterator.h" >+#include "JSCInlines.h" >+ >+namespace JSC { >+ >+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DirectArguments); >+ >+const ClassInfo DirectArguments::s_info = { "Arguments", &Base::s_info, 0, CREATE_METHOD_TABLE(DirectArguments) }; >+ >+DirectArguments::DirectArguments(VM& vm, Structure* structure, unsigned length) >+ : Base(vm, structure) >+ , m_length(length) >+{ >+} >+ >+DirectArguments* DirectArguments::createUninitialized(VM& vm, Structure* structure, unsigned length) >+{ >+ DirectArguments* result = >+ new (NotNull, allocateCell<DirectArguments>(vm.heap, allocationSize(length))) >+ (vm, structure); >+ result->finishCreation(vm); >+ return result; >+} >+ >+DirectArguments* DirectArguments::create(VM& vm, Structure* structure, unsigned length) >+{ >+ DirectArguments* result = createUninitialized(vm, structure, length); >+ >+ for (unsigned i = length; i--;) >+ result->storage()[i].clear(); >+ >+ return result; >+} >+ >+DirectArguments* DirectArguments::createByCopying(VM& vm, Structure* structure, ExecState* exec) >+{ >+ unsigned length = exec->argumentCount(); >+ DirectArguments* result = createUninitialized(vm, structure, length); >+ >+ for (unsigned i = length; i--;) >+ result->storage()[i].set(vm, result, exec->uncheckedArgument(i)); >+ >+ result->callee().set(vm, result, jsCast<JSFunction*>(exec->callee())); >+ >+ return result; >+} >+ >+void DirectArguments::visitChildren(JSCell* thisCell, SlotVisitor& visitor) >+{ >+ DirectArguments* thisObject = static_cast<DirectArguments*>(thisCell); >+ ASSERT_GC_OBJECT_INHERITS(thisObject, info()); >+ Base::visitChildren(thisObject, visitor); >+ >+ visitor.appendValues(thisObject->storage(), thisObject->m_length); >+} >+ >+Structure* DirectArguments::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) >+{ >+ return Structure::create(vm, globalObject, prototype, TypeInfo(DirectArgumentsType, StructureFlags), info()); >+} >+ >+bool DirectArguments::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName ident, PropertySlot& slot) >+{ >+ DirectArguments* thisObject = jsCast<DirectArguments*>(object); >+ VM& vm = exec->vm(); >+ >+ if (!thisObject->m_overrides) { >+ if (ident == vm.propertyNames->length) { >+ slot.setValue(thisObject, DontEnum, jsNumber(thisObject->m_length)); >+ return true; >+ } else if (ident == vm.propertyNames->callee) { >+ if (!thisObject->isStrictMode()) { >+ slot.setValue(thisObject, DontEnum, thisObject->callee().get()); >+ return true; >+ } >+ thisObject->slowDownAndWasteMemory(vm); >+ } else if (ident == vm.propertyNames->caller) >+ thisObject->slowDownAndWasteMemory(vm); >+ } >+ >+ unsigned index = ident.asIndex(); >+ if (thisObject->canAccessIndexQuickly(index)) { >+ slot.setValue(thisObject, None, thisObject->getIndexQuickly(index)); >+ return true; >+ } >+ >+ if (Base::getOwnPropertySlot(thisObject, exec, ident, slot)) >+ return true; >+ >+ if (ident == vm.propertyNames->iteratorPrivateName) { >+ JSGlobalObject* globalObject = exec->lexicalGlobalObject(); >+ thisObject->JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorPrivateName, argumentsFuncIterator, DontEnum, 0); >+ if (JSObject::getOwnPropertySlot(thisObject, exec, ident, slot)) >+ return true; >+ } >+ >+ return false; >+} >+ >+bool DirectArguments::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot) >+{ >+ DirectArguments* thisObject = jsCast<DirectArguments*>(object); >+ >+ if (thisObject->canAccessIndexQuickly(index)) { >+ slot.setValue(thisObject, None, thisObject->getIndexQuickly(index)); >+ return true; >+ } >+ >+ return Base::getOwnPropertySlotByIndex(object, exec, index, slot); >+} >+ >+void DirectArguments::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode) >+{ >+ DirectArguments* thisObject = jsCast<DirectArguments*>(object); >+ >+ for (unsigned i = 0; i < thisObject->m_length; ++i) { >+ if (!thisObject->canAccessIndexQuickly(index)) >+ continue; >+ array.add(Identifier::from(exec, i)); >+ } >+ if (shouldIncludeDontEnumProperties(mode) && !m_overrides) { >+ array.add(exec->propertyNames().callee); >+ array.add(exec->propertyNames().length); >+ } >+ Base::getOwnPropertyNames(thisObject, exec, array, mode); >+} >+ >+void DirectArguments::put(JSCell* cell, ExecState* exec, PropertyName ident, JSValue value, PutPropertySlot& slot) >+{ >+ DirectArguments* thisObject = jsCast<DirectArguments*>(object); >+ VM& vm = exec->vm(); >+ >+ if (!thisObject->m_overrides >+ && (ident == vm.propertyNames->length >+ || ident == vm.propertyNames->callee >+ || ident == vm.propertyNames->caller)) >+ thisObject->slowDownAndWasteMemory(vm); >+ >+ unsigned index = ident.asIndex(); >+ if (thisObject->canAccessIndexQuickly(index)) { >+ setIndexQuickly(vm, index, value); >+ return; >+ } >+ >+ Base::put(thisObject, exec, ident, value, slot); >+} >+ >+void DirectArguments::putByIndex(JSCell* cell, ExecState* exec, unsigned index, JSValue value, bool shouldThrow) >+{ >+ DirectArguments* thisObject = jsCast<DirectArguments*>(object); >+ VM& vm = exec->vm(); >+ >+ if (thisObject->canSetIndexQuickly(index)) { >+ setIndexQuickly(vm, index, value); >+ return; >+ } >+ >+ return Base::putByIndex(cell, exec, index, value, shouldThrow); >+} >+ >+void DirectArguments::deleteProperty(JSCell* cell, ExecState* exec, PropertyName ident) >+{ >+ DirectArguments* thisObject = jsCast<DirectArguments*>(object); >+ VM& vm = exec->vm(); >+ >+ if (!thisObject->m_overrides >+ && (ident == vm.propertyNames->length >+ || ident == vm.propertyNames->callee >+ || ident == vm.propertyNames->caller)) >+ thisObject->slowDownAndWasteMemory(vm); >+ >+ unsigned index = ident.asIndex(); >+ if (thisObject->canAccessIndexQuickly(index)) { >+ thisObject->slowDownAndWasteMemoryIfNecessary(vm); >+ thisObject->m_overrides.get()[index] = true; >+ return; >+ } >+ >+ Base::deleteProperty(thisObject, exec, ident); >+} >+ >+void DirectArguments::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned index) >+{ >+ DirectArguments* thisObject = jsCast<DirectArguments*>(object); >+ VM& vm = exec->vm(); >+ >+ if (thisObject->canAccessIndexQuickly(index)) { >+ thisObject->slowDownAndWasteMemoryIfNecessary(vm); >+ thisObject->m_overrides.get()[index] = true; >+ return; >+ } >+ >+ return Base::deletePropertyByIndex(cell, exec, index); >+} >+ >+void DirectArguments::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName ident, const PropertyDescriptor& descriptor, bool shouldThrow) >+{ >+ DirectArguments* thisObject = jsCast<DirectArguments*>(object); >+ VM& vm = exec->vm(); >+ >+ if (!thisObject->m_overrides >+ && (ident == vm.propertyNames->length >+ || ident == vm.propertyNames->callee >+ || ident == vm.propertyNames->caller)) >+ thisObject->slowDownAndWasteMemory(vm); >+ >+ unsigned index = ident.asIndex(); >+ if (index < thisObject->m_length) { >+ // If this property >+ // FIXME: this will be a struggle. >+ if (!thisObject->canAccessIndexQuickly(index)) >+ } >+} >+ >+void DirectArguments::slowDownAndWasteMemory(VM& vm) >+{ >+ RELEASE_ASSERT(!m_overrides); >+ >+ putDirect(vm, vm.propertyNames->length, jsNumber(m_length), DontEnum); >+ >+ if (isStrictMode()) { >+ putDirectNonIndexAccessor(vm, vm.propertyNames->callee, globalObject()->throwTypeErrorGetterSetter(vm), DontEnum | DontDelete | Accessor); >+ putDirectNonIndexAccessor(vm, vm.propertyNames->caller, globalObject()->throwTypeErrorGetterSetter(vm), DontEnum | DontDelete | Accessor); >+ } else >+ putDirect(vm, vm.propertyNames->callee, m_callee.get(), DontEnum); >+ >+ void* backingStore; >+ RELEASE_ASSERT(vm.heap.tryAllocateStorage(this, m_length), &backingStore); >+ m_overrides.set(vm, this, static_cast<bool*>(backingStore)); >+ for (unsigned i = m_length; i--;) >+ m_overrides.get()[i] = false; >+} >+ >+void DirectArguments::slowDownAndWasteMemoryIfNecessary(VM& vm) >+{ >+ if (!m_overrides) >+ slowDownAndWasteMemory(vm); >+} >+ >+} // namespace JSC >+ >Index: Source/JavaScriptCore/runtime/DirectArguments.h >=================================================================== >--- Source/JavaScriptCore/runtime/DirectArguments.h (revision 0) >+++ Source/JavaScriptCore/runtime/DirectArguments.h (working copy) >@@ -0,0 +1,158 @@ >+/* >+ * Copyright (C) 2015 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 DirectArguments_h >+#define DirectArguments_h >+ >+#include "JSObject.h" >+ >+namespace JSC { >+ >+// This is an Arguments-class object that we create when you say "arguments" inside a function, >+// and none of the arguments are captured in the function's activation. The function will copy all >+// of its arguments into this object, and all subsequent accesses to the arguments will go through >+// this object thereafter. Special support is in place for mischevious events like the arguments >+// being deleted (something like "delete arguments[0]") or reconfigured (broadly, we say deletions >+// and reconfigurations mean that the respective argument was "overridden"). >+// >+// To speed allocation, this object will hold all of the arguments in-place. The arguments as well >+// as a table of flags saying which arguments were overridden. >+class DirectArguments : public JSNonFinalObject { >+public: >+ typedef JSNonFinalObject Base; >+ >+private: >+ DirectArguments(VM&, Structure*, unsigned length); >+ >+public: >+ // Creates an arguments object but leaves it uninitialized. >+ static DirectArguments* createUninitialized(VM&, Structure*, unsigned length); >+ >+ // Creates an arguments object and initializes everything to the empty value. >+ static DirectArguments* create(VM&, Structure*, unsigned length); >+ >+ // Creates an arguments object by copying the argumnets from the stack. >+ static DirectArguments* createByCopying(VM&, Structure*, ExecState*); >+ >+ static void visitChildren(JSCell*, SlotVisitor&); >+ static void copyBackingStore(JSCell*, CopyVisitor&, CopyToken); >+ >+ uint32_t length(ExecState* exec) const >+ { >+ if (UNLIKELY(m_overrides)) >+ return get(exec, exec->propertyNames().length).toUInt32(exec); >+ return m_length; >+ } >+ >+ bool canAccessIndexQuickly(uint32_t i) const >+ { >+ return i < m_length && (!m_overrides || !m_overrides.get()[i]); >+ } >+ >+ JSValue getIndexQuickly(uint32_t i) const >+ { >+ ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i)); >+ return storage()[i].get(); >+ } >+ >+ void setIndexQuickly(VM& vm, uint32_t i, JSValue value) >+ { >+ ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i)); >+ storage()[i].set(vm, this, value); >+ } >+ >+ WriteBarrier<JSFunction>& callee() >+ { >+ return m_callee; >+ } >+ >+ WriteBarrier<Unknown>& argument(CapturedArgumentsOffset offset) >+ { >+ ASSERT(offset); >+ ASSERT_WITH_SECURITY_IMPLICATION(offset.offset() < m_length); >+ return storage()[offset.offset()]; >+ } >+ >+ FunctionExecutable* executable() >+ { >+ return jsCast<FunctionExecutable*>(callee->executable()); >+ } >+ >+ bool isStrictMode() >+ { >+ return executable()->isStrictMode(); >+ } >+ >+ DECLARE_INFO; >+ >+ static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype); >+ >+private: >+ static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); >+ static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&); >+ static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); >+ static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); >+ static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); >+ static void deleteProperty(JSCell*, ExecState*, PropertyName); >+ static void deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); >+ static void defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow); >+ >+ void slowDownAndWasteMemory(VM&); >+ void slowDownAndWasteMemoryIfNecessary(VM&); >+ >+ static size_t storageOffset() >+ { >+ return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(DirectArguments)); >+ } >+ >+ static size_t overrideFlagsOffset(uint32_t length) >+ { >+ return storageOffset() + sizeof(WriteBarrier<Unknown>) * length; >+ } >+ >+ static size_t allocationSize(uint32_t length) >+ { >+ return overrideFlagsOffset(length) + WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(length); >+ } >+ >+ WriteBarrier<Unknown>* storage() >+ { >+ return bitwise_cast<WriteBarrier<Unknown>*>(bitwise_cast<char*>(this) + storageOffset()); >+ } >+ >+ bool* overrideFlags() >+ { >+ return bitwise_cast<WriteBarrier<Unknown>*>(bitwise_cast<char*>(this) + overrideFlagsOffset(m_length)); >+ } >+ >+ WriteBarrier<JSFunction*> m_callee; >+ uint32_t m_length; // Always the actual length of captured arguments and never what was stored into the length property. >+ CopyWriteBarrier<bool> m_overrides; // If non-null, it means that length, callee, and caller are fully materialized properties. >+}; >+ >+} // namespace JSC >+ >+#endif // DirectArguments_h >+ >Index: Source/JavaScriptCore/runtime/ForeignVariableIndex.h >=================================================================== >--- Source/JavaScriptCore/runtime/ForeignVariableIndex.h (revision 0) >+++ Source/JavaScriptCore/runtime/ForeignVariableIndex.h (working copy) >@@ -0,0 +1,52 @@ >+/* >+ * Copyright (C) 2015 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 ForeignVariableIndex_h >+#define ForeignVariableIndex_h >+ >+namespace JSC { >+ >+class ForeignVariableIndex { >+public: >+ ForeignVariableIndex() >+ : m_index(UINT_MAX) >+ { >+ } >+ >+ explicit ForeignVariableIndex(unsigned index) >+ : m_index(index) >+ { >+ } >+ >+ >+ >+private: >+ unsigned m_index; >+}; >+ >+} // namespace JSC >+ >+#endif // ForeignVariableIndex_h >+ >Index: Source/JavaScriptCore/runtime/GenericOffset.h >=================================================================== >--- Source/JavaScriptCore/runtime/GenericOffset.h (revision 0) >+++ Source/JavaScriptCore/runtime/GenericOffset.h (working copy) >@@ -0,0 +1,111 @@ >+/* >+ * Copyright (C) 2015 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 GenericOffset_h >+#define GenericOffset_h >+ >+#include <wtf/Assertions.h> >+ >+namespace JSC { >+ >+// A mixin for creating the various kinds of variable offsets that our engine supports. >+template<typename T> >+class GenericOffset { >+public: >+ static const unsigned invalidOffset = UINT_MAX; >+ >+ GenericOffset() >+ : m_offset(invalidOffset) >+ { >+ } >+ >+ explicit GenericOffset(unsigned offset) >+ : m_offset(offset) >+ { >+ } >+ >+ bool operator!() const { return m_offset == invalidOffset; } >+ >+ unsigned offsetUnchecked() const >+ { >+ return m_offset; >+ } >+ >+ unsigned offset() const >+ { >+ ASSERT(m_offset != invalidOffset); >+ return m_offset; >+ } >+ >+ bool operator==(const T& other) const >+ { >+ return m_offset == other.offsetUnchecked(); >+ } >+ bool operator!=(const T& other) const >+ { >+ return m_offset != other.offsetUnchecked(); >+ } >+ bool operator<(const T& other) const >+ { >+ return m_offset < other.offsetUnchecked(); >+ } >+ bool operator>(const T& other) const >+ { >+ return m_offset > other.offsetUnchecked(); >+ } >+ bool operator<=(const T& other) const >+ { >+ return m_offset <= other.offsetUnchecked(); >+ } >+ bool operator>=(const T& other) const >+ { >+ return m_offset >= other.offsetUnchecked(); >+ } >+ >+ T operator+(int value) const >+ { >+ return T(offset() + value); >+ } >+ T operator-(int value) const >+ { >+ return T(offset() - value); >+ } >+ T& operator+=(int value) >+ { >+ return *this = *this + value; >+ } >+ T& operator-=(int value) >+ { >+ return *this = *this - value; >+ } >+ >+private: >+ unsigned m_offset; >+}; >+ >+} // namespace JSC >+ >+#endif // GenericOffset_h >+ >Index: Source/JavaScriptCore/runtime/JSArgumentsIterator.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSArgumentsIterator.cpp (revision 180529) >+++ Source/JavaScriptCore/runtime/JSArgumentsIterator.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2013 Apple, Inc. All rights reserved. >+ * Copyright (C) 2013, 2015 Apple, Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -33,10 +33,18 @@ namespace JSC { > > const ClassInfo JSArgumentsIterator::s_info = { "ArgumentsIterator", &Base::s_info, 0, CREATE_METHOD_TABLE(JSArgumentsIterator) }; > >-void JSArgumentsIterator::finishCreation(VM& vm, Arguments* arguments) >+void JSArgumentsIterator::finishCreation(VM& vm, JSObject* arguments) > { > Base::finishCreation(vm); > m_arguments.set(vm, this, arguments); > } > >+EncodedJSValue JSC_HOST_CALL argumentsFuncIterator(ExecState* exec) >+{ >+ JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec); >+ if (!thisObj->inherits(Arguments::info()) && !thisObj->inherits(OutOfBandArguments::info())) >+ return JSValue::encode(throwTypeError(exec, ASCIILiteral("Attempted to use Arguments iterator on non-Arguments object"))); >+ return JSValue::encode(JSArgumentsIterator::create(exec->vm(), exec->callee()->globalObject()->argumentsIteratorStructure(), thisObj)); >+} >+ > } >Index: Source/JavaScriptCore/runtime/JSArgumentsIterator.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSArgumentsIterator.h (revision 180529) >+++ Source/JavaScriptCore/runtime/JSArgumentsIterator.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2013 Apple, Inc. All rights reserved. >+ * Copyright (C) 2013, 2015 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,7 +26,7 @@ > #ifndef JSArgumentsIterator_h > #define JSArgumentsIterator_h > >-#include "Arguments.h" >+#include "JSObject.h" > > namespace JSC { > >@@ -41,7 +41,7 @@ public: > return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); > } > >- static JSArgumentsIterator* create(VM& vm, Structure* structure, Arguments* arguments) >+ static JSArgumentsIterator* create(VM& vm, Structure* structure, JSObject* arguments) > { > JSArgumentsIterator* instance = new (NotNull, allocateCell<JSArgumentsIterator>(vm.heap)) JSArgumentsIterator(vm, structure); > instance->finishCreation(vm, arguments); >@@ -50,11 +50,11 @@ public: > > bool next(CallFrame* callFrame, JSValue& value) > { >- if (m_nextIndex >= m_arguments->length(callFrame)) >+ unsigned length = >+ m_arguments->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame); >+ if (m_nextIndex >= length) > return false; >- value = m_arguments->tryGetArgument(m_nextIndex++); >- if (!value) >- value = jsUndefined(); >+ value = m_arguments->getIndex(callFrame, m_nextIndex++); > return true; > } > >@@ -68,12 +68,14 @@ private: > { > } > >- void finishCreation(VM&, Arguments*); >+ void finishCreation(VM&, JSObject*); > >- WriteBarrier<Arguments> m_arguments; >+ WriteBarrier<JSObject> m_arguments; > size_t m_nextIndex; > }; > >+EncodedJSValue JSC_HOST_CALL argumentsFuncIterator(ExecState*); >+ > } > > #endif // !defined(JSArgumentsIterator_h) >Index: Source/JavaScriptCore/runtime/JSEnvironmentRecord.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSEnvironmentRecord.cpp (revision 180529) >+++ Source/JavaScriptCore/runtime/JSEnvironmentRecord.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2007, 2008, 2012 Apple Inc. All rights reserved. >+ * Copyright (C) 2007, 2008, 2012, 2015 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -35,4 +35,12 @@ namespace JSC { > > const ClassInfo JSEnvironmentRecord::s_info = { "EnvironmentRecord", &Base::s_info, 0, CREATE_METHOD_TABLE(JSEnvironmentRecord) }; > >+void JSEnvironmentRecord::visitChildren(JSCell* cell, SlotVisitor& visitor) >+{ >+ JSEnvironmentRecord* thisObject = jsCast<JSEnvironmentRecord*>(cell); >+ ASSERT_GC_OBJECT_INHERITS(thisObject, info()); >+ Base::visitChildren(thisObject, visitor); >+ visitor.appendValues(thisObject->variables(), m_symbolTable->scopeSize()); >+} >+ > } // namespace JSC >Index: Source/JavaScriptCore/runtime/JSEnvironmentRecord.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSEnvironmentRecord.h (revision 180529) >+++ Source/JavaScriptCore/runtime/JSEnvironmentRecord.h (working copy) >@@ -46,11 +46,26 @@ class JSEnvironmentRecord : public JSSym > public: > typedef JSSymbolTableObject Base; > >- WriteBarrierBase<Unknown>* registers() { return m_registers; } >- WriteBarrierBase<Unknown>& registerAt(int index) const { return m_registers[index]; } >+ WriteBarrierBase<Unknown>* variables() >+ { >+ return bitwise_cast<WriteBarrierBase<Unknown>*>(bitwise_cast<char*>(this) + offsetOfVariables()); >+ } >+ >+ bool isValid(ScopeOffset offset) >+ { >+ return !!offset && offset.offset() < m_symbolTable->scopeSize(); >+ } >+ >+ WriteBarrierBase<Unknown>& variableAt(ScopeOffset offset) const >+ { >+ ASSERT(isValid(offset)); >+ return variables()[offset.offset()]; >+ } > >- WriteBarrierBase<Unknown>* const * addressOfRegisters() const { return &m_registers; } >- static size_t offsetOfRegisters() { return OBJECT_OFFSETOF(JSEnvironmentRecord, m_registers); } >+ static size_t offsetOfVariables() >+ { >+ return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSEnvironmentRecord)); >+ } > > DECLARE_INFO; > >@@ -60,15 +75,35 @@ protected: > JSEnvironmentRecord( > VM& vm, > Structure* structure, >- Register* registers, > JSScope* scope, > SymbolTable* symbolTable) > : Base(vm, structure, scope, symbolTable) >- , m_registers(reinterpret_cast<WriteBarrierBase<Unknown>*>(registers)) > { > } >- >- WriteBarrierBase<Unknown>* m_registers; // "r" in the stack. >+ >+ static size_t allocationSizeForScopeSize(unsigned scopeSize) >+ { >+ return offsetOfVariables() + scopeSize * sizeof(WriteBarrier<Unknown>); >+ } >+ >+ static size_t allocationSize(SymbolTable* symbolTable) >+ { >+ return allocationSizeForScopeSize(symbolTable->scopeSize()); >+ } >+ >+ void finishCreationUninitialized(VM& vm) >+ { >+ Base::finishCreation(vm); >+ } >+ >+ void finishCreation(VM& vm) >+ { >+ finishCreationUninitialized(vm); >+ for (unsigned i = m_symbolTable->scopeSize(); i--;) { >+ // Filling this with undefined is useful because that's what variables start out as. >+ variableAt(i).setUndefined(); >+ } >+ } > }; > > } // namespace JSC >Index: Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp (revision 180529) >+++ Source/JavaScriptCore/runtime/JSLexicalEnvironment.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2008, 2009, 2014 Apple Inc. All rights reserved. >+ * Copyright (C) 2008, 2009, 2014, 2015 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -40,27 +40,19 @@ namespace JSC { > > const ClassInfo JSLexicalEnvironment::s_info = { "JSLexicalEnvironment", &Base::s_info, 0, CREATE_METHOD_TABLE(JSLexicalEnvironment) }; > >-void JSLexicalEnvironment::visitChildren(JSCell* cell, SlotVisitor& visitor) >-{ >- JSLexicalEnvironment* thisObject = jsCast<JSLexicalEnvironment*>(cell); >- ASSERT_GC_OBJECT_INHERITS(thisObject, info()); >- Base::visitChildren(thisObject, visitor); >- >- for (int i = 0; i < thisObject->symbolTable()->captureCount(); ++i) >- visitor.append(&thisObject->storage()[i]); >-} >- > inline bool JSLexicalEnvironment::symbolTableGet(PropertyName propertyName, PropertySlot& slot) > { > SymbolTableEntry entry = symbolTable()->inlineGet(propertyName.uid()); > if (entry.isNull()) > return false; > >+ ScopeOffset offset = entry.scopeOffset(); >+ > // Defend against the inspector asking for a var after it has been optimized out. >- if (!isValid(entry)) >+ if (!isValid(offset)) > return false; > >- slot.setValue(this, DontEnum, registerAt(entry.getIndex()).get()); >+ slot.setValue(this, DontEnum, variableAt(offset).get()); > return true; > } > >@@ -70,11 +62,13 @@ inline bool JSLexicalEnvironment::symbol > if (entry.isNull()) > return false; > >+ ScopeOffset offset = entry.scopeOffset(); >+ > // Defend against the inspector asking for a var after it has been optimized out. >- if (!isValid(entry)) >+ if (!isValid(offset)) > return false; > >- descriptor.setDescriptor(registerAt(entry.getIndex()).get(), entry.getAttributes()); >+ descriptor.setDescriptor(variableAt(offset).get(), entry.getAttributes()); > return true; > } > >@@ -95,12 +89,13 @@ inline bool JSLexicalEnvironment::symbol > throwTypeError(exec, StrictModeReadonlyPropertyWriteError); > return true; > } >+ ScopeOffset offset = iter->value.scopeOffset(); > // Defend against the inspector asking for a var after it has been optimized out. >- if (!isValid(iter->value)) >+ if (!isValid(offset)) > return false; > if (VariableWatchpointSet* set = iter->value.watchpointSet()) >- set->invalidate(VariableWriteFireDetail(this, propertyName)); // Don't mess around - if we had found this statically, we would have invcalidated it. >- reg = ®isterAt(iter->value.getIndex()); >+ set->invalidate(VariableWriteFireDetail(this, propertyName)); // Don't mess around - if we had found this statically, we would have invalidated it. >+ reg = &variableAt(offset); > } > reg->set(vm, this, value); > return true; >@@ -116,7 +111,7 @@ void JSLexicalEnvironment::getOwnNonInde > for (SymbolTable::Map::iterator it = thisObject->symbolTable()->begin(locker); it != end; ++it) { > if (it->value.getAttributes() & DontEnum && !shouldIncludeDontEnumProperties(mode)) > continue; >- if (!thisObject->isValid(it->value)) >+ if (!thisObject->isValid(it->value.scopeOffset())) > continue; > propertyNames.add(Identifier(exec, it->key.get())); > } >@@ -137,11 +132,13 @@ inline bool JSLexicalEnvironment::symbol > return false; > SymbolTableEntry& entry = iter->value; > ASSERT(!entry.isNull()); >- if (!isValid(entry)) >+ >+ ScopeOffset offset = entry.scopeOffset(); >+ if (!isValid(offset)) > return false; > > entry.setAttributes(attributes); >- reg = ®isterAt(entry.getIndex()); >+ reg = &variableAt(offset); > } > reg->set(vm, this, value); > return true; >Index: Source/JavaScriptCore/runtime/JSLexicalEnvironment.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSLexicalEnvironment.h (revision 180529) >+++ Source/JavaScriptCore/runtime/JSLexicalEnvironment.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2008, 2009, 2013, 2014 Apple Inc. All rights reserved. >+ * Copyright (C) 2008, 2009, 2013-2015 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -41,33 +41,27 @@ class Register; > > class JSLexicalEnvironment : public JSEnvironmentRecord { > private: >- JSLexicalEnvironment(VM&, CallFrame*, Register*, JSScope*, CodeBlock*); >+ JSLexicalEnvironment(VM&, Structure*, JSScope*, SymbolTable*); > > public: > typedef JSEnvironmentRecord Base; > >- static JSLexicalEnvironment* create(VM& vm, CallFrame* callFrame, Register* registers, JSScope* currentScope, CodeBlock* codeBlock) >+ static JSLexicalEnvironment* create( >+ VM& vm, JSGlobalObject* globalObject, JSScope* currentScope, SymbolTable* symbolTable) > { >- SymbolTable* symbolTable = codeBlock->symbolTable(); >- ASSERT(codeBlock->codeType() == FunctionCode); >- JSLexicalEnvironment* lexicalEnvironment = new ( >- NotNull, >- allocateCell<JSLexicalEnvironment>( >- vm.heap, >- allocationSize(symbolTable) >- ) >- ) JSLexicalEnvironment(vm, callFrame, registers, currentScope, codeBlock); >- lexicalEnvironment->finishCreation(vm); >- return lexicalEnvironment; >+ JSLexicalEnvironment* result = >+ new (NotNull, allocationSize(symbolTable)) >+ JSLexicalEnvironment(vm, globalObject->activationStructure(), currentScope, symbolTable); >+ result->finishCreation(vm); > } >- >+ > static JSLexicalEnvironment* create(VM& vm, CallFrame* callFrame, JSScope* currentScope, CodeBlock* codeBlock) > { >- return create(vm, callFrame, callFrame->registers() + codeBlock->framePointerOffsetToGetActivationRegisters(), currentScope, codeBlock); >+ JSGlobalObject* globalObject = callFrame->lexicalGlobalObject(); >+ SymbolTable* symbolTable = codeBlock->symbolTable(); >+ return create(vm, globalObject, currentScope, symboltable); > } >- >- static void visitChildren(JSCell*, SlotVisitor&); >- >+ > static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); > static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); > >@@ -81,12 +75,6 @@ public: > > static Structure* createStructure(VM& vm, JSGlobalObject* globalObject) { return Structure::create(vm, globalObject, jsNull(), TypeInfo(ActivationObjectType, StructureFlags), info()); } > >- WriteBarrierBase<Unknown>& registerAt(int) const; >- bool isValidIndex(int) const; >- bool isValid(const SymbolTableEntry&) const; >- int registersOffset(); >- static int registersOffset(SymbolTable*); >- > protected: > static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | Base::StructureFlags; > >@@ -96,32 +84,13 @@ private: > bool symbolTableGet(PropertyName, PropertySlot&, bool& slotIsWriteable); > bool symbolTablePut(ExecState*, PropertyName, JSValue, bool shouldThrow); > bool symbolTablePutWithAttributes(VM&, PropertyName, JSValue, unsigned attributes); >- >- static size_t allocationSize(SymbolTable*); >- static size_t storageOffset(); >- >- WriteBarrier<Unknown>* storage(); // captureCount() number of registers. > }; > >-inline JSLexicalEnvironment::JSLexicalEnvironment(VM& vm, CallFrame* callFrame, Register* registers, JSScope* currentScope, CodeBlock* codeBlock) >- : Base( >- vm, >- callFrame->lexicalGlobalObject()->activationStructure(), >- registers, >- currentScope, >- codeBlock->symbolTable()) >+inline JSLexicalEnvironment::JSLexicalEnvironment(VM& vm, Structure* structure, JSScope* currentScope, SymbolTable* symbolTable) >+ : Base(vm, structure, currentScope, symbolTable) > { >- SymbolTable* symbolTable = codeBlock->symbolTable(); >- WriteBarrier<Unknown>* storage = this->storage(); >- size_t captureCount = symbolTable->captureCount(); >- for (size_t i = 0; i < captureCount; ++i) >- new (NotNull, &storage[i]) WriteBarrier<Unknown>(UndefinedWriteBarrierTag); >- m_registers = reinterpret_cast_ptr<WriteBarrierBase<Unknown>*>( >- reinterpret_cast<char*>(this) + registersOffset(symbolTable)); > } > >-JSLexicalEnvironment* asActivation(JSValue); >- > inline JSLexicalEnvironment* asActivation(JSValue value) > { > ASSERT(asObject(value)->inherits(JSLexicalEnvironment::info())); >@@ -133,49 +102,6 @@ ALWAYS_INLINE JSLexicalEnvironment* Regi > return asActivation(jsValue()); > } > >-inline int JSLexicalEnvironment::registersOffset(SymbolTable* symbolTable) >-{ >- return storageOffset() + ((symbolTable->captureCount() - symbolTable->captureStart() - 1) * sizeof(WriteBarrier<Unknown>)); >-} >- >-inline size_t JSLexicalEnvironment::storageOffset() >-{ >- return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSLexicalEnvironment)); >-} >- >-inline WriteBarrier<Unknown>* JSLexicalEnvironment::storage() >-{ >- return reinterpret_cast_ptr<WriteBarrier<Unknown>*>( >- reinterpret_cast<char*>(this) + storageOffset()); >-} >- >-inline size_t JSLexicalEnvironment::allocationSize(SymbolTable* symbolTable) >-{ >- size_t objectSizeInBytes = WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSLexicalEnvironment)); >- size_t storageSizeInBytes = symbolTable->captureCount() * sizeof(WriteBarrier<Unknown>); >- return objectSizeInBytes + storageSizeInBytes; >-} >- >-inline bool JSLexicalEnvironment::isValidIndex(int index) const >-{ >- if (index > symbolTable()->captureStart()) >- return false; >- if (index <= symbolTable()->captureEnd()) >- return false; >- return true; >-} >- >-inline bool JSLexicalEnvironment::isValid(const SymbolTableEntry& entry) const >-{ >- return isValidIndex(entry.getIndex()); >-} >- >-inline WriteBarrierBase<Unknown>& JSLexicalEnvironment::registerAt(int index) const >-{ >- ASSERT(isValidIndex(index)); >- return Base::registerAt(index); >-} >- > } // namespace JSC > > #endif // JSLexicalEnvironment_h >Index: Source/JavaScriptCore/runtime/JSNameScope.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSNameScope.cpp (revision 180529) >+++ Source/JavaScriptCore/runtime/JSNameScope.cpp (working copy) >@@ -47,14 +47,6 @@ JSNameScope* JSNameScope::create(VM& vm, > return nullptr; > } > >-void JSNameScope::visitChildren(JSCell* cell, SlotVisitor& visitor) >-{ >- JSNameScope* thisObject = jsCast<JSNameScope*>(cell); >- ASSERT_GC_OBJECT_INHERITS(thisObject, info()); >- Base::visitChildren(thisObject, visitor); >- visitor.append(&thisObject->m_registerStore); >-} >- > JSValue JSNameScope::toThis(JSCell*, ExecState* exec, ECMAMode ecmaMode) > { > if (ecmaMode == StrictMode) >Index: Source/JavaScriptCore/runtime/JSNameScope.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSNameScope.h (revision 180529) >+++ Source/JavaScriptCore/runtime/JSNameScope.h (working copy) >@@ -44,38 +44,37 @@ public: > template<typename T> > static T* create(VM& vm, JSGlobalObject* globalObject, JSScope* currentScope, SymbolTable* symbolTable, JSValue value) > { >- T* scopeObject = new (NotNull, allocateCell<T>(vm.heap)) T(vm, globalObject, currentScope, symbolTable); >+ T* scopeObject = new ( >+ NotNull, allocateCell<T>(vm.heap, allocationSizeForScopeSize(1)) >+ T(vm, globalObject, currentScope, symbolTable); > scopeObject->finishCreation(vm, value); > return scopeObject; > } > > static JSNameScope* create(VM&, JSGlobalObject*, JSScope* currentScope, SymbolTable*, JSValue, Type); > >- static void visitChildren(JSCell*, SlotVisitor&); > static JSValue toThis(JSCell*, ExecState*, ECMAMode); > static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); > static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); > > DECLARE_INFO; > >- JSValue value() const { return m_registerStore.get(); } >+ JSValue value() const { return variableAt(0).get(); } > > protected: > void finishCreation(VM& vm, JSValue value) > { >- Base::finishCreation(vm); >- m_registerStore.set(vm, this, value); >+ Base::finishCreationUninitialized(vm); >+ variableAt(0).set(vm, this, value); > } > > static const unsigned StructureFlags = OverridesGetOwnPropertySlot | Base::StructureFlags; > > JSNameScope(VM& vm, Structure* structure, JSScope* next, SymbolTable* symbolTable) >- : Base(vm, structure, reinterpret_cast<Register*>(&m_registerStore + 1), next, symbolTable) >+ : Base(vm, structure, next, symbolTable) > { >+ ASSERT(symbolTable->scopeSize() == 1); > } >- >-private: >- WriteBarrier<Unknown> m_registerStore; > }; > > } >Index: Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp (revision 180529) >+++ Source/JavaScriptCore/runtime/JSSegmentedVariableObject.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved. >+ * Copyright (C) 2012, 2013, 2015 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -33,32 +33,30 @@ > > namespace JSC { > >-int JSSegmentedVariableObject::findRegisterIndex(void* registerAddress) >+ScopeOffset JSSegmentedVariableObject::findRegisterIndex(void* registerAddress) > { > ConcurrentJITLocker locker(m_lock); > >- for (int i = m_registers.size(); i--;) { >+ for (unsigned i = m_registers.size(); i--;) { > if (&m_registers[i] != registerAddress) > continue; >- return i; >+ return ScopeOffset(i); > } > CRASH(); >- return -1; >+ return ScopeOffset(); > } > >-int JSSegmentedVariableObject::addRegisters(int numberOfRegistersToAdd) >+ScopeOffset JSSegmentedVariableObject::addRegisters(unsigned numberOfRegistersToAdd) > { > ConcurrentJITLocker locker(m_lock); > >- ASSERT(numberOfRegistersToAdd >= 0); >- > size_t oldSize = m_registers.size(); > m_registers.grow(oldSize + numberOfRegistersToAdd); > > for (size_t i = numberOfRegistersToAdd; i--;) > m_registers[oldSize + i].setWithoutWriteBarrier(jsUndefined()); > >- return static_cast<int>(oldSize); >+ return ScopeOffset(oldSize); > } > > void JSSegmentedVariableObject::visitChildren(JSCell* cell, SlotVisitor& slotVisitor) >Index: Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h (revision 180529) >+++ Source/JavaScriptCore/runtime/JSSegmentedVariableObject.h (working copy) >@@ -57,24 +57,23 @@ class JSSegmentedVariableObject : public > public: > typedef JSSymbolTableObject Base; > >- WriteBarrier<Unknown>& registerAt(int index) { return m_registers[index]; } >+ WriteBarrier<Unknown>& variableAt(ScopeOffset offset) { return m_variables[offset.offset()]; } > > // This is a slow method call, which searches the register bank to find the index > // given a pointer. It will CRASH() if it does not find the register. Only use this > // in debug code (like bytecode dumping). >- JS_EXPORT_PRIVATE int findRegisterIndex(void*); >+ JS_EXPORT_PRIVATE ScopeOffset findRegisterIndex(void*); > >- WriteBarrier<Unknown>* assertRegisterIsInThisObject(WriteBarrier<Unknown>* registerPointer) >+ WriteBarrier<Unknown>* assertVariableIsInThisObject(WriteBarrier<Unknown>* variablePointer) > { >-#if !ASSERT_DISABLED >- findRegisterIndex(registerPointer); >-#endif >+ if (!ASSERT_DISABLED) >+ findRegisterIndex(registerPointer); > return registerPointer; > } > > // Adds numberOfRegistersToAdd registers, initializes them to Undefined, and returns > // the index of the first one added. >- JS_EXPORT_PRIVATE int addRegisters(int numberOfRegistersToAdd); >+ JS_EXPORT_PRIVATE ScopeOffset addRegisters(unsigned numberOfRegistersToAdd); > > JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); > >Index: Source/JavaScriptCore/runtime/JSSymbolTableObject.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSSymbolTableObject.h (revision 180529) >+++ Source/JavaScriptCore/runtime/JSSymbolTableObject.h (working copy) >@@ -78,7 +78,7 @@ inline bool symbolTableGet( > return false; > SymbolTableEntry::Fast entry = iter->value; > ASSERT(!entry.isNull()); >- slot.setValue(object, entry.getAttributes() | DontDelete, object->registerAt(entry.getIndex()).get()); >+ slot.setValue(object, entry.getAttributes() | DontDelete, object->variableAt(entry.scopeOffset()).get()); > return true; > } > >@@ -94,7 +94,7 @@ inline bool symbolTableGet( > SymbolTableEntry::Fast entry = iter->value; > ASSERT(!entry.isNull()); > descriptor.setDescriptor( >- object->registerAt(entry.getIndex()).get(), entry.getAttributes() | DontDelete); >+ object->variableAt(entry.scopeOffset()).get(), entry.getAttributes() | DontDelete); > return true; > } > >@@ -110,7 +110,7 @@ inline bool symbolTableGet( > return false; > SymbolTableEntry::Fast entry = iter->value; > ASSERT(!entry.isNull()); >- slot.setValue(object, entry.getAttributes() | DontDelete, object->registerAt(entry.getIndex()).get()); >+ slot.setValue(object, entry.getAttributes() | DontDelete, object->variableAt(entry.scopeOffset()).get()); > slotIsWriteable = !entry.isReadOnly(); > return true; > } >@@ -145,7 +145,7 @@ inline bool symbolTablePut( > // https://bugs.webkit.org/show_bug.cgi?id=134601 > set->notifyWrite(vm, value, object, propertyName); > } >- reg = &object->registerAt(fastEntry.getIndex()); >+ reg = &object->variableAt(fastEntry.scopeOffset()); > } > // I'd prefer we not hold lock while executing barriers, since I prefer to reserve > // the right for barriers to be able to trigger GC. And I don't want to hold VM >@@ -173,7 +173,7 @@ inline bool symbolTablePutWithAttributes > if (VariableWatchpointSet* set = entry.watchpointSet()) > set->notifyWrite(vm, value, object, propertyName); > entry.setAttributes(attributes); >- reg = &object->registerAt(entry.getIndex()); >+ reg = &object->variableAt(entry.scopeOffset()); > } > reg->set(vm, object, value); > return true; >Index: Source/JavaScriptCore/runtime/OutOfBandArguments.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/OutOfBandArguments.cpp (revision 0) >+++ Source/JavaScriptCore/runtime/OutOfBandArguments.cpp (working copy) >@@ -0,0 +1,126 @@ >+/* >+ * Copyright (C) 2015 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 "OutOfBandArguments.h" >+ >+#include "JSArgumentsIterator.h" >+#include "JSCInlines.h" >+ >+namespace JSC { >+ >+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(OutOfBandArguments); >+ >+const ClassInfo OutOfBandArguments::s_info = { "Arguments", &Base::s_info, 0, CREATE_METHOD_TABLE(OutOfBandArguments) }; >+ >+OutOfBandArguments::OutOfBandArguments(VM& vm, Structure* structure) >+ : Base(vm, structure, nullptr) >+{ >+} >+ >+OutOfBandArguments* OutOfBandArguments::createEmpty(VM& vm, JSGlobalObject* globalObject) >+{ >+ OutOfBandArguments* result = new (NotNull, allocateCell<OutOfBandArguments>(vm.heap)) >+ OutOfBandArguments(vm, globalObject->outOfBandArgumentsStructure()); >+ result->finishCreation(vm); >+ return result; >+} >+ >+OutOfBandArguments* OutOfBandArguments::createEmpty(ExecState* exec) >+{ >+ // NB. Some clients might expect that the global object of of this object is the global object >+ // of the callee. We don't do this for now, but maybe we should. >+ return createEmpty(exec->vm(), exec->lexicalGlobalObject()); >+} >+ >+OutOfBandArguments* OutOfBandArguments::createWithInlineFrame(ExecState* myFrame, ExecState* targetFrame, InlineCallFrame* inlineCallFrame, ArgumentsMode mode) >+{ >+ VM& vm = myFrame->vm(); >+ >+ JSFunction* callee; >+ FunctionExecutable* executable; >+ >+ if (inlineCallFrame) { >+ callee = jsCast<JSFunction*>(inlineCallFrame->calleeRecovery.recover(targetFrame)); >+ executable = jsCast<FunctionExecutable*>(inlineCallFrame->executable.get()); >+ } else { >+ callee = jsCast<JSFunction*>(targetFrame->callee()); >+ executable = jsCast<FunctionExecutable*>(targetFrame->codeBlock()->ownerExecutable()); >+ } >+ >+ // NB. It's somewhat arbitrary that we tie the strictness of this object to the strictness of >+ // the callee. >+ bool isStrictMode = executable->isStrictMode(); >+ >+ OutOfBandArguments* result = createEmpty(myFrame); >+ >+ unsigned length; >+ switch (mode) { >+ case ClonedArgumentsCreationMode: { >+ if (inlineCallFrame) { >+ if (inlineCallFrame->argumentCountRegister.isValid()) >+ length = exec->r(inlineCallFrame->argumentCountRegister).unboxedInt32(); >+ else >+ length = inlineCallFrame->arguments.size(); >+ length--; >+ >+ for (unsigned i = length; i--;) >+ result->putDirectIndex(myFrame, i, inlineCallFrame->arguments[i].recover(targetFrame)); >+ } else { >+ length = targetFrame->argumentCount(); >+ >+ for (unsigned i = length; i--;) >+ result->putDirectIndex(myFrame, i, targetFrame->uncheckedArgument(i)); >+ } >+ break; >+ } >+ >+ case FakeArgumentValuesCreationMode: { >+ length = 0; >+ break; >+ } } >+ >+ result->putDirect(vm, vm.propertyNames->length, jsNumber(length)); >+ if (isStrictMode) { >+ result->putDirectAccessor(exec, vm.propertyNames->callee, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor); >+ result->putDirectAccessor(exec, vm.propertyNames->callee, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor); >+ } else >+ result->putDirect(vm, vm.propertyNames->callee, JSValue(callee)); >+ >+ result->JSC_NATIVE_FUNCTION(vm.propertyNames->iteratorPrivateName, argumentsFuncIterator, DontEnum, 0); >+} >+ >+OutOfBandArguments* OutOfBandArguments::createWithMachineFrame(ExecState* myFrame, ExecState* targetFrame, ArgumentsMode mode) >+{ >+ return createWithInlineFrame(myFrame, targetFrame, nullptr, mode); >+} >+ >+Structure* OutOfBandArguments::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) >+{ >+ return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); >+} >+ >+} // namespace JSC >+ >Index: Source/JavaScriptCore/runtime/OutOfBandArguments.h >=================================================================== >--- Source/JavaScriptCore/runtime/OutOfBandArguments.h (revision 0) >+++ Source/JavaScriptCore/runtime/OutOfBandArguments.h (working copy) >@@ -0,0 +1,64 @@ >+/* >+ * Copyright (C) 2015 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 OutOfBandArguments_h >+#define OutOfBandArguments_h >+ >+#include "ArgumentsMode.h" >+#include "JSObject.h" >+ >+namespace JSC { >+ >+// This is an Arguments-class object that we create when you do function.arguments. It behaves >+// entirely like an ordinary JavaScript object. All of the arguments values are simply copied from >+// the stack (possibly via some sophisticated ValueRecovery's if an optimizing compiler is in >+// play) and the appropriate properties of the object are populated. The only reason why we need >+// a special class is to make the object claim to be "Arguments" from a toString standpoint. >+// >+// Note that this class does a bad job of being fast. That's somewhat intentional. We expect uses >+// of function.arguments to be rare on the modern web. You will get particularly bad performance >+// if you use function.arguments in strict mode. >+class OutOfBandArguments : public JSNonFinalObject { >+public: >+ typedef JSNonFinalObject Base; >+ >+private: >+ OutOfBandArguments(VM&, Structure*); >+ >+public: >+ static OutOfBandArguments* createEmpty(VM&, JSGlobalObject*); >+ static OutOfBandArguments* createEmpty(ExecState*); >+ static OutOfBandArguments* createWithInlineFrame(ExecState* myFrame, ExecState* targetFrame, InlineCallFrame*, ArgumentsMode); >+ static OutOfBandArguments* createWithMachineFrame(ExecState* myFrame, ExecState* targetFrame, ArgumentsMode); >+ >+ static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype); >+ >+ DECLARE_INFO; >+}; >+ >+} // namespace JSC >+ >+#endif // OutOfBandArguments_h >+ >Index: Source/JavaScriptCore/runtime/ScopeOffset.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/ScopeOffset.cpp (revision 0) >+++ Source/JavaScriptCore/runtime/ScopeOffset.cpp (working copy) >@@ -0,0 +1,42 @@ >+/* >+ * Copyright (C) 2015 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 "ScopeOffset.h" >+ >+namespace JSC { >+ >+void ScopeOffset::dump(PrintStream& out) const >+{ >+ if (!*this) { >+ out.print("scopeInvalid"); >+ return; >+ } >+ >+ out.print("scope", offset()); >+} >+ >+} // namespace JSC >+ >Index: Source/JavaScriptCore/runtime/ScopeOffset.h >=================================================================== >--- Source/JavaScriptCore/runtime/ScopeOffset.h (revision 0) >+++ Source/JavaScriptCore/runtime/ScopeOffset.h (working copy) >@@ -0,0 +1,51 @@ >+/* >+ * Copyright (C) 2015 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 ScopeOffset_h >+#define ScopeOffset_h >+ >+#include "GenericOffset.h" >+#include <wtf/PrintStream.h> >+ >+namespace JSC { >+ >+// This is an offset into a scope of some kind. It could be an activation scope or it could be a >+// global object. >+class ScopeOffset : public GenericOffset<ScopeOffset> { >+public: >+ ScopeOffset() { } >+ >+ explicit ScopeOffset(unsigned offset) >+ : GenericOffset(offset) >+ { >+ } >+ >+ void dump(PrintStream&) const; >+}; >+ >+} // namespace JSC >+ >+#endif // ScopeOffset_h >+ >Index: Source/JavaScriptCore/runtime/ScopedArguments.h >=================================================================== >--- Source/JavaScriptCore/runtime/ScopedArguments.h (revision 0) >+++ Source/JavaScriptCore/runtime/ScopedArguments.h (working copy) >@@ -0,0 +1,95 @@ >+/* >+ * Copyright (C) 2015 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 ScopedArguments_h >+#define ScopedArguments_h >+ >+#include "JSObject.h" >+ >+namespace JSC { >+ >+// This is an Arguments-class object that we create when you say "arguments" inside a function, >+// and one or more of the arguments may be captured in the function's activation. The function >+// will copy all of its arguments into the activation and then create this object. This object >+// will use the symbol table's ScopedArgumentsTable and the activation to handle all indexed >+// lookups. >+class ScopedArguments : public JSNonFinalObject { >+public: >+ typedef JSNonFinalObject Base; >+ >+private: >+ ScopedArguments(VM&, Structure*); >+ >+public: >+ static ScopedArguments* create(VM&, Structure*, ScopedArgumentsTable*, JSLexicalEnvironment*); >+ >+ static void visitChildren(JSCell*, SlotVisitor&); >+ >+ uint32_t length(ExecState* exec) const >+ { >+ if (UNLIKELY(m_overrodeLength)) >+ return get(exec, exec->propertyNames().length).toUInt32(exec); >+ return m_table->length(); >+ } >+ >+ bool canGetIndexQuickly(uint32_t i) const >+ { >+ return i < m_length && !!m_table->get(i); >+ } >+ >+ JSValue getIndexQuickly(uint32_t i) const >+ { >+ ASSERT_WITH_SECURITY_IMPLICATION(canGetIndexQuickly(i)); >+ return m_scope->variableAt(m_table->get(i)).get(); >+ } >+ >+ DECLARE_INFO; >+ >+ static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype); >+ >+private: >+ static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&); >+ static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&); >+ static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); >+ static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&); >+ static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow); >+ static void deleteProperty(JSCell*, ExecState*, PropertyName); >+ static void deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); >+ static void defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow); >+ >+ void overrideArgument(VM& vm, uint32_t i) >+ { >+ m_table.set(vm, this, m_table->set(vm, i, ScopeOffset())); >+ } >+ >+ bool m_overrodeLength; >+ WriteBarrier<ScopedArgumentsTable> m_table; >+ WriteBarrier<JSLexicalEnvironment> m_scope; >+}; >+ >+} // namespace JSC >+ >+#endif // ScopedArguments_h >+ >Index: Source/JavaScriptCore/runtime/ScopedArgumentsTable.h >=================================================================== >--- Source/JavaScriptCore/runtime/ScopedArgumentsTable.h (revision 0) >+++ Source/JavaScriptCore/runtime/ScopedArgumentsTable.h (working copy) >@@ -0,0 +1,91 @@ >+/* >+ * Copyright (C) 2015 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 ScopedArgumentsTable_h >+#define ScopedArgumentsTable_h >+ >+#include "JSCell.h" >+ >+namespace JSC { >+ >+// This class's only job is to hold onto the list of ScopeOffsets for each argument that a >+// function has. Most of the time, the BytecodeGenerator will create one of these and it will >+// never be modified subsequently. There is a rare case where a ScopedArguments object is created >+// and aliases one of these and then decides to modify it; in that case we do copy-on-write. This >+// makes sense because such modifications are so uncommon. You'd have to do something crazy like >+// "delete arguments[i]" or some variant of defineOwnProperty. >+class ScopedArguments : public JSCell { >+public: >+ typedef JSCell Base; >+ >+ static const bool needsDestruction = true; >+ static const bool hasImmortalStructure = true; >+ >+private: >+ ScopedArgumentsTable(VM&); >+ ~ScopedArgumentsTable(); >+ >+public: >+ static ScopedArgumentsTable* create(VM&); >+ >+ ScopedArguments* clone(VM&); >+ >+ uint32_t length() const { return m_length; } >+ ScopedArgumentsTable* setLength(VM&, uint32_t newLength); >+ >+ ScopeOffset get(uint32_t i) const >+ { >+ ASSERT_WITH_SECURITY_IMPLICATION(i < m_length); >+ return m_arguments[i]; >+ } >+ >+ void lock() >+ { >+ m_locked = true; >+ } >+ >+ ScopedArguments* set(VM& vm, uint32_t i, ScopeOffset value) >+ { >+ ScopedArguments* result; >+ if (UNLIKELY(m_locked)) >+ result = clone(vm); >+ else >+ result = this; >+ result->setDirect(i, value); >+ return result; >+ } >+ >+ DECLARE_INFO; >+ >+private: >+ uint32_t m_length; >+ bool m_locked; // Being locked means that there are multiple references to this object and none of them expect to see the others' modifications. This means that modifications need to make a copy first. >+ std::unique_ptr<ScopeOffset[]> m_arguments; >+}; >+ >+} // namespace JSC >+ >+#endif // ScopedArgumentsTable_h >+ >Index: Source/JavaScriptCore/runtime/SymbolTable.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/SymbolTable.cpp (revision 180529) >+++ Source/JavaScriptCore/runtime/SymbolTable.cpp (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2012, 2014 Apple Inc. All rights reserved. >+ * Copyright (C) 2012, 2014, 2015 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -137,29 +137,22 @@ void SymbolTable::WatchpointCleanup::fin > } > } > >-SymbolTable* SymbolTable::cloneCapturedNames(VM& vm) >+SymbolTable* SymbolTable::cloneScopePart(VM& vm) > { > SymbolTable* result = SymbolTable::create(vm); > >- result->m_parameterCountIncludingThis = m_parameterCountIncludingThis; > result->m_usesNonStrictEval = m_usesNonStrictEval; >- result->m_captureStart = m_captureStart; >- result->m_captureEnd = m_captureEnd; > > for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) { >- if (!isCaptured(iter->value.getIndex())) >+ if (!iter->value.varOffset().isScope()) > continue; > result->m_map.add( > iter->key, >- SymbolTableEntry(iter->value.getIndex(), iter->value.getAttributes())); >+ SymbolTableEntry(iter->value.varOffset(), iter->value.getAttributes())); > } > >- if (m_slowArguments) { >- result->m_slowArguments = std::make_unique<SlowArgument[]>(parameterCount()); >- for (unsigned i = parameterCount(); i--;) >- result->m_slowArguments[i] = m_slowArguments[i]; >- } >- >+ result->m_arguments = arguments(); >+ > if (m_typeProfilingRareData) { > result->m_typeProfilingRareData = std::make_unique<TypeProfilingRareData>(); > >Index: Source/JavaScriptCore/runtime/SymbolTable.h >=================================================================== >--- Source/JavaScriptCore/runtime/SymbolTable.h (revision 180529) >+++ Source/JavaScriptCore/runtime/SymbolTable.h (working copy) >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2007, 2008, 2012-2014 Apple Inc. All rights reserved. >+ * Copyright (C) 2007, 2008, 2012-2015 Apple Inc. All rights reserved. > * > * Redistribution and use in source and binary forms, with or without > * modification, are permitted provided that the following conditions >@@ -31,6 +31,7 @@ > > #include "ConcurrentJITLock.h" > #include "JSObject.h" >+#include "ScopedArgumentsTable.h" > #include "TypeLocation.h" > #include "VariableWatchpointSet.h" > #include <memory> >@@ -39,24 +40,6 @@ > > namespace JSC { > >-struct SlowArgument { >-public: >- enum Status { >- Normal = 0, >- Captured = 1, >- Deleted = 2 >- }; >- >- SlowArgument() >- : status(Normal) >- , index(0) >- { >- } >- >- Status status; >- int index; // If status is 'Deleted', index is bogus. >-}; >- > static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits<int>::max(); } > > // The bit twiddling in this class assumes that every register index is a >@@ -86,6 +69,28 @@ static ALWAYS_INLINE int missingSymbolMa > // copy: SymbolTableEntry --> FatEntry -----^ > > struct SymbolTableEntry { >+private: >+ static VarOffset varOffsetFromBits(intptr_t bits) >+ { >+ VarKind kind; >+ if (bits & StackFlag) >+ kind = StackVarKind; >+ else if (bits & CapturedArgumentFlag) >+ kind = CapturedArgumentKind; >+ else >+ kind = ScopeVarKind; >+ return VarOffset::assemble(kind, static_cast<int>(bits >> FlagBits)); >+ } >+ >+ static ScopeOffset scopeOffsetFromBits(intptr_t bits) >+ { >+ ASSERT(!(bits & StackFlag)); >+ ASSERT(!(bits & CapturedArgumentFlag)); >+ return ScopeOffset(static_cast<int>(bits >> FlagBits)); >+ } >+ >+public: >+ > // Use the SymbolTableEntry::Fast class, either via implicit cast or by calling > // getFast(), when you (1) only care about isNull(), getIndex(), and isReadOnly(), > // and (2) you are in a hot path where you need to minimize the number of times >@@ -107,11 +112,19 @@ struct SymbolTableEntry { > return !(m_bits & ~SlimFlag); > } > >- int getIndex() const >+ VarOffset varOffset() const > { >- return static_cast<int>(m_bits >> FlagBits); >+ return varOffsetFromBits(m_bits); > } >- >+ >+ // Asserts if the offset is anything but a scope offset. This structures the assertions >+ // in a way that may result in better code, even in release, than doing >+ // varOffset().scopeOffset(). >+ ScopeOffset scopeOffset() const >+ { >+ return scopeOffsetFromBits(m_bits); >+ } >+ > bool isReadOnly() const > { > return m_bits & ReadOnlyFlag; >@@ -142,18 +155,18 @@ struct SymbolTableEntry { > { > } > >- SymbolTableEntry(int index) >+ SymbolTableEntry(VarOffset offset) > : m_bits(SlimFlag) > { >- ASSERT(isValidIndex(index)); >- pack(index, false, false); >+ ASSERT(isValidVarOffset(offset)); >+ pack(offset, false, false); > } > >- SymbolTableEntry(int index, unsigned attributes) >+ SymbolTableEntry(VarOffset offset, unsigned attributes) > : m_bits(SlimFlag) > { >- ASSERT(isValidIndex(index)); >- pack(index, attributes & ReadOnly, attributes & DontEnum); >+ ASSERT(isValidVarOffset(offset)); >+ pack(offset, attributes & ReadOnly, attributes & DontEnum); > } > > ~SymbolTableEntry() >@@ -181,9 +194,17 @@ struct SymbolTableEntry { > return !(bits() & ~SlimFlag); > } > >- int getIndex() const >+ VarOffset varOffset() const >+ { >+ return varOffsetFromBits(bits()); >+ } >+ >+ // Asserts if the offset is anything but a scope offset. This structures the assertions >+ // in a way that may result in better code, even in release, than doing >+ // varOffset().scopeOffset(). >+ ScopeOffset scopeOffset() const > { >- return static_cast<int>(bits() >> FlagBits); >+ return scopeOffsetFromBits(bits()); > } > > ALWAYS_INLINE Fast getFast() const >@@ -209,7 +230,7 @@ struct SymbolTableEntry { > > void setAttributes(unsigned attributes) > { >- pack(getIndex(), attributes & ReadOnly, attributes & DontEnum); >+ pack(varOffset(), attributes & ReadOnly, attributes & DontEnum); > } > > bool isReadOnly() const >@@ -242,7 +263,9 @@ private: > static const intptr_t ReadOnlyFlag = 0x2; > static const intptr_t DontEnumFlag = 0x4; > static const intptr_t NotNullFlag = 0x8; >- static const intptr_t FlagBits = 4; >+ static const intptr_t StackFlag = 0x10; >+ static const intptr_t CapturedArgumentFlag = 0x20; >+ static const intptr_t FlagBits = 6; > > class FatEntry { > WTF_MAKE_FAST_ALLOCATED; >@@ -309,20 +332,34 @@ private: > > JS_EXPORT_PRIVATE void freeFatEntrySlow(); > >- void pack(int index, bool readOnly, bool dontEnum) >+ void pack(VarOffset offset, bool readOnly, bool dontEnum) > { > ASSERT(!isFat()); > intptr_t& bitsRef = bits(); >- bitsRef = (static_cast<intptr_t>(index) << FlagBits) | NotNullFlag | SlimFlag; >+ bitsRef = >+ (static_cast<intptr_t>(offset.rawOffset()) << FlagBits) | NotNullFlag | SlimFlag; > if (readOnly) > bitsRef |= ReadOnlyFlag; > if (dontEnum) > bitsRef |= DontEnumFlag; >+ switch (offset.kind()) { >+ case ScopeVarKind: >+ break; >+ case StackVarKind: >+ bitsRef |= StackFlag; >+ break; >+ case CapturedArgumentKind: >+ bitsRef |= CapturedArgumentFlag; >+ break; >+ default: >+ RELEASE_ASSERT_NOT_REACHED(); >+ break; >+ } > } > >- bool isValidIndex(int index) >+ static bool isValidVarOffset(VarOffset offset) > { >- return ((static_cast<intptr_t>(index) << FlagBits) >> FlagBits) == static_cast<intptr_t>(index); >+ return ((static_cast<intptr_t>(offset.rawOffset()) << FlagBits) >> FlagBits) == static_cast<intptr_t>(offset.rawOffset()); > } > > intptr_t m_bits; >@@ -351,7 +388,7 @@ public: > static SymbolTable* createNameScopeTable(VM& vm, const Identifier& ident, unsigned attributes) > { > SymbolTable* result = create(vm); >- result->add(ident.impl(), SymbolTableEntry(-1, attributes)); >+ result->add(ident.impl(), SymbolTableEntry(VarOffset(ScopeOffset(0)), attributes)); > return result; > } > >@@ -423,8 +460,29 @@ public: > return size(locker); > } > >+ ScopeOffset maxScopeOffset() const >+ { >+ return m_maxScopeOffset; >+ } >+ >+ unsigned scopeSize() const >+ { >+ ScopeOffset maxScopeOffset = this->maxScopeOffset(); >+ >+ // Do some calculation that relies on invalid scope offset plus one being zero. >+ unsigned fastResult = maxScopeOffset.offsetUnchecked() + 1; >+ >+ // Assert that this works. >+ ASSERT(fastResult == (!maxScopeOffset ? 0 : maxScopeOffset.offset() + 1)); >+ >+ return fastResult; >+ } >+ > Map::AddResult add(const ConcurrentJITLocker&, StringImpl* key, const SymbolTableEntry& entry) > { >+ if (entry.varOffset().isScope() >+ && (!m_maxScopeOffset || m_maxScopeOffset < entry.scopeOffset())) >+ m_maxScopeOffset = entry.scopeOffset(); > return m_map.add(key, entry); > } > >@@ -456,6 +514,45 @@ public: > return contains(locker, key); > } > >+ // The principle behind ScopedArgumentsTable modifications is that we will create one and >+ // leave it unlocked - thereby allowing in-place changes - until someone asks for a pointer to >+ // the table. Then, we will lock it. Then both our future changes and their future changes >+ // will first have to make a copy. This discipline means that usually when we create a >+ // ScopedArguments object, we don't have to make a copy of the ScopedArgumentsTable - instead >+ // we just take a reference to one that we already have. >+ >+ uint32_t argumentsLength() const >+ { >+ if (!m_arguments) >+ return 0; >+ return m_arguments->length(); >+ } >+ >+ void setArgumentsLength(VM& vm, uint32_t length) >+ { >+ if (UNLIKELY(!m_arguments)) >+ m_arguments.set(vm, this, ScopedArgumentsTable::create(vm)); >+ m_arguments.set(vm, this, m_arguments->setLength(vm, length)); >+ } >+ >+ ScopeOffset argumentOffset(uint32_t i) const >+ { >+ ASSERT_WITH_SECURITY_IMPLICATION(m_arguments); >+ return m_arguments->get(i); >+ } >+ >+ void setArgumentOffset(VM& vm, uint32_t i, ScopeOffset offset) >+ { >+ ASSERT_WITH_SECURITY_IMPLICATION(m_arguments); >+ m_arguments.set(vm, this, m_arguments->set(vm, i, offset)); >+ } >+ >+ ScopedArgumentsTable* arguments() const >+ { >+ m_arguments->lock(); >+ return m_arguments.get(); >+ } >+ > GlobalVariableID uniqueIDForVariable(const ConcurrentJITLocker&, StringImpl* key, VM& vm); > GlobalVariableID uniqueIDForRegister(const ConcurrentJITLocker& locker, int registerIndex, VM& vm); > RefPtr<TypeSet> globalTypeSetForRegister(const ConcurrentJITLocker& locker, int registerIndex, VM& vm); >@@ -464,28 +561,7 @@ public: > bool usesNonStrictEval() { return m_usesNonStrictEval; } > void setUsesNonStrictEval(bool usesNonStrictEval) { m_usesNonStrictEval = usesNonStrictEval; } > >- int captureStart() const { return m_captureStart; } >- void setCaptureStart(int captureStart) { m_captureStart = captureStart; } >- >- int captureEnd() const { return m_captureEnd; } >- void setCaptureEnd(int captureEnd) { m_captureEnd = captureEnd; } >- >- int captureCount() const { return -(m_captureEnd - m_captureStart); } >- >- bool isCaptured(int operand) >- { >- return operand <= captureStart() && operand > captureEnd(); >- } >- >- int parameterCount() { return m_parameterCountIncludingThis - 1; } >- int parameterCountIncludingThis() { return m_parameterCountIncludingThis; } >- void setParameterCountIncludingThis(int parameterCountIncludingThis) { m_parameterCountIncludingThis = parameterCountIncludingThis; } >- >- // 0 if we don't capture any arguments; parameterCount() in length if we do. >- const SlowArgument* slowArguments() { return m_slowArguments.get(); } >- void setSlowArguments(std::unique_ptr<SlowArgument[]> slowArguments) { m_slowArguments = WTF::move(slowArguments); } >- >- SymbolTable* cloneCapturedNames(VM&); >+ SymbolTable* cloneScopePart(VM&); > > void prepareForTypeProfiling(const ConcurrentJITLocker&); > >@@ -513,6 +589,8 @@ private: > ~SymbolTable(); > > Map m_map; >+ ScopeOffset m_maxScopeOffset; >+ > struct TypeProfilingRareData { > UniqueIDMap m_uniqueIDMap; > RegisterToVariableMap m_registerToVariableMap; >@@ -520,13 +598,9 @@ private: > }; > std::unique_ptr<TypeProfilingRareData> m_typeProfilingRareData; > >- int m_parameterCountIncludingThis; > bool m_usesNonStrictEval; >- >- int m_captureStart; >- int m_captureEnd; >- >- std::unique_ptr<SlowArgument[]> m_slowArguments; >+ >+ WriteBarrier<ScopedArgumentsTable> m_arguments; > > std::unique_ptr<WatchpointCleanup> m_watchpointCleanup; > >Index: Source/JavaScriptCore/runtime/VarOffset.cpp >=================================================================== >--- Source/JavaScriptCore/runtime/VarOffset.cpp (revision 0) >+++ Source/JavaScriptCore/runtime/VarOffset.cpp (working copy) >@@ -0,0 +1,76 @@ >+/* >+ * Copyright (C) 2015 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 "VarOffset.h" >+ >+namespace JSC { >+ >+void VarOffset::dump(PrintStream& out) const >+{ >+ switch (m_kind) { >+ case InvalidVarKind: >+ out.print("invalid"); >+ return; >+ case ScopeVarKind: >+ out.print(scopeOffset()); >+ return; >+ case StackVarKind: >+ out.print(stackOffset()); >+ return; >+ case CapturedArgumentKind: >+ out.print(capturedArgumentOffset()); >+ return; >+ } >+ RELEASE_ASSERT_NOT_REACHED(); >+} >+ >+} // namespace JSC >+ >+namespace WTF { >+ >+using namespace JSC; >+ >+void printInternal(PrintStream& out, VarKind varKind) >+{ >+ switch (varKind) { >+ case InvalidVarKind: >+ out.print("Invalid"); >+ return; >+ case ScopeVarKind: >+ out.print("Scope"); >+ return; >+ case StackVarKind: >+ out.print("Stack"); >+ return; >+ case CapturedArgumentKind: >+ out.print("CapturedArgument"); >+ return; >+ } >+ RELEASE_ASSERT_NOT_REACHED(); >+} >+ >+} // namespace WTF >+ >Index: Source/JavaScriptCore/runtime/VarOffset.h >=================================================================== >--- Source/JavaScriptCore/runtime/VarOffset.h (revision 0) >+++ Source/JavaScriptCore/runtime/VarOffset.h (working copy) >@@ -0,0 +1,214 @@ >+/* >+ * Copyright (C) 2015 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 VarOffset_h >+#define VarOffset_h >+ >+#include "CapturedArgumentOffset.h" >+#include "ScopeOffset.h" >+#include "VirtualRegister.h" >+ >+namespace JSC { >+ >+enum VarKind : uint8_t { >+ InvalidVarKind, >+ ScopeVarKind, >+ StackVarKind, >+ CapturedArgumentKind >+}; >+ >+class VarOffset { >+public: >+ VarOffset() >+ : m_kind(InvalidVarKind) >+ , m_offset(UINT_MAX) >+ { >+ } >+ >+ explicit VarOffset(VirtualRegister stackOffset) >+ { >+ if (!stackOffset.isValid()) { >+ m_kind = InvalidVarKind; >+ m_offset = UINT_MAX; >+ } else { >+ m_kind = StackVarKind; >+ m_offset = stackOffset.offset(); >+ } >+ } >+ >+ explicit VarOffset(ScopeOffset scopeOffset) >+ { >+ if (!scopeOffset) { >+ m_kind = InvalidVarKind; >+ m_offset = UINT_MAX; >+ } else { >+ m_kind = ScopeVarKind; >+ m_offset = scopeOffset.offset(); >+ } >+ } >+ >+ explicit VarOffset(CapturedArgumentOffset capturedArgumentOffset) >+ { >+ if (!capturedArgumentOffset) { >+ m_kind = InvalidVarKind; >+ m_offset = UINT_MAX; >+ } else { >+ m_kind = CapturedArgumentKind; >+ m_offset = capturedArgumentOffset.offset(); >+ } >+ } >+ >+ static VarOffset assemble(VarKind kind, unsigned offset) >+ { >+ VarOffset result; >+ result.m_kind = kind; >+ result.m_offset = offset; >+ result.checkSanity(); >+ return result; >+ } >+ >+ bool isValid() const >+ { >+ return m_kind != InvalidVarKind; >+ } >+ >+ bool operator!() const >+ { >+ return !isValid(); >+ } >+ >+ VarKind kind() const { return m_kind; } >+ >+ bool isStack() const >+ { >+ return m_kind == StackVarKind; >+ } >+ >+ bool isScope() const >+ { >+ return m_kind == ScopeVarKind; >+ } >+ >+ bool isCapturedArgument() const >+ { >+ return m_kind == CapturedArgumentKind; >+ } >+ >+ VirtualRegister stackOffsetUnchecked() const >+ { >+ if (!isStack()) >+ return VirtualRegister(); >+ return VirtualRegister(m_offset); >+ } >+ >+ ScopeOffset scopeOffsetUnchecked() const >+ { >+ if (!isScope()) >+ return ScopeOffset(); >+ return ScopeOffset(m_offset); >+ } >+ >+ CapturedArgumentOffset capturedArgumentOffsetUnchecked() const >+ { >+ if (!isCapturedArgument()) >+ return CapturedArgumentOffset(); >+ return CapturedArgumentOffset(m_offset); >+ } >+ >+ VirtualRegister stackOffset() const >+ { >+ ASSERT(isStack()); >+ return VirtualRegister(m_offset); >+ } >+ >+ ScopeOffset scopeOffset() const >+ { >+ ASSERT(isScope()); >+ return ScopeOffset(m_offset); >+ } >+ >+ CapturedArgumentOffset capturedArgumentOffset() const >+ { >+ ASSERT(isCapturedArgument()); >+ return CapturedArgumentOffset(m_offset); >+ } >+ >+ unsigned rawOffset() const >+ { >+ ASSERT(isValid()); >+ return m_offset; >+ } >+ >+ void checkSanity() const >+ { >+ if (ASSERT_DISABLED) >+ return; >+ >+ switch (m_kind) { >+ case InvalidVarKind: >+ ASSERT(m_offset == UINT_MAX); >+ return; >+ case ScopeVarKind: >+ ASSERT(scopeOffset()); >+ return; >+ case StackVarKind: >+ ASSERT(stackOffset()); >+ return; >+ case CapturedArgumentKind: >+ ASSERT(capturedArgumentOffset()); >+ return; >+ } >+ >+ ASSERT_NOT_REACHED(); >+ } >+ >+ bool operator==(const VarOffset& other) const >+ { >+ return m_kind == other.m_kind >+ && m_offset == other.m_offset; >+ } >+ >+ bool operator!=(const VarOffset& other) const >+ { >+ return !(*this == other); >+ } >+ >+ void dump(PrintStream&) const; >+ >+private: >+ VarKind m_kind; >+ unsigned m_offset; >+}; >+ >+} // namespace JSC >+ >+namespace WTF { >+ >+void printInternal(PrintStream&, JSC::VarKind); >+ >+} // namespace WTF >+ >+#endif // VarOffset_h >+ >Index: Source/JavaScriptCore/runtime/VariableLocation.h >=================================================================== >--- Source/JavaScriptCore/runtime/VariableLocation.h (revision 0) >+++ Source/JavaScriptCore/runtime/VariableLocation.h (working copy) >@@ -0,0 +1,38 @@ >+/* >+ * Copyright (C) 2015 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 VariableLocation_h >+#define VariableLocation_h >+ >+#include "VirtualRegister.h" >+ >+namespace JSC { >+ >+ >+ >+} // namespace JSC >+ >+#endif // VariableLocation_h >+
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 141951
:
247199
|
247200
|
247201