summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/runtime/JSSymbolTableObject.h
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSSymbolTableObject.h')
-rw-r--r--Source/JavaScriptCore/runtime/JSSymbolTableObject.h172
1 files changed, 111 insertions, 61 deletions
diff --git a/Source/JavaScriptCore/runtime/JSSymbolTableObject.h b/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
index b5b20a845..366b5a012 100644
--- a/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
+++ b/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2014-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,7 +10,7 @@
* 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -26,43 +26,53 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSSymbolTableObject_h
-#define JSSymbolTableObject_h
+#pragma once
#include "JSScope.h"
#include "PropertyDescriptor.h"
#include "SymbolTable.h"
+#include "ThrowScope.h"
+#include "VariableWriteFireDetail.h"
namespace JSC {
class JSSymbolTableObject : public JSScope {
public:
typedef JSScope Base;
+ static const unsigned StructureFlags = Base::StructureFlags | OverridesGetPropertyNames;
SymbolTable* symbolTable() const { return m_symbolTable.get(); }
JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, PropertyName);
JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ static ptrdiff_t offsetOfSymbolTable() { return OBJECT_OFFSETOF(JSSymbolTableObject, m_symbolTable); }
+
+ DECLARE_EXPORT_INFO;
+
protected:
- static const unsigned StructureFlags = IsEnvironmentRecord | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags;
+ JSSymbolTableObject(VM& vm, Structure* structure, JSScope* scope)
+ : Base(vm, structure, scope)
+ {
+ }
- JSSymbolTableObject(VM& vm, Structure* structure, JSScope* scope, SymbolTable* symbolTable = 0)
+ JSSymbolTableObject(VM& vm, Structure* structure, JSScope* scope, SymbolTable* symbolTable)
: Base(vm, structure, scope)
{
- if (symbolTable)
- m_symbolTable.set(vm, this, symbolTable);
+ ASSERT(symbolTable);
+ setSymbolTable(vm, symbolTable);
}
-
- void finishCreation(VM& vm)
+
+ void setSymbolTable(VM& vm, SymbolTable* symbolTable)
{
- Base::finishCreation(vm);
- if (!m_symbolTable)
- m_symbolTable.set(vm, this, SymbolTable::create(vm));
+ ASSERT(!m_symbolTable);
+ symbolTable->singletonScope()->notifyWrite(vm, this, "Allocated a scope");
+ m_symbolTable.set(vm, this, symbolTable);
}
-
+
static void visitChildren(JSCell*, SlotVisitor&);
-
+
+private:
WriteBarrier<SymbolTable> m_symbolTable;
};
@@ -71,13 +81,19 @@ inline bool symbolTableGet(
SymbolTableObjectType* object, PropertyName propertyName, PropertySlot& slot)
{
SymbolTable& symbolTable = *object->symbolTable();
- ConcurrentJITLocker locker(symbolTable.m_lock);
- SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.publicName());
+ ConcurrentJSLocker locker(symbolTable.m_lock);
+ SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
if (iter == symbolTable.end(locker))
return false;
SymbolTableEntry::Fast entry = iter->value;
ASSERT(!entry.isNull());
- slot.setValue(object, entry.getAttributes() | DontDelete, object->registerAt(entry.getIndex()).get());
+
+ ScopeOffset offset = entry.scopeOffset();
+ // Defend against the inspector asking for a var after it has been optimized out.
+ if (!object->isValidScopeOffset(offset))
+ return false;
+
+ slot.setValue(object, entry.getAttributes() | DontDelete, object->variableAt(offset).get());
return true;
}
@@ -86,14 +102,19 @@ inline bool symbolTableGet(
SymbolTableObjectType* object, PropertyName propertyName, PropertyDescriptor& descriptor)
{
SymbolTable& symbolTable = *object->symbolTable();
- ConcurrentJITLocker locker(symbolTable.m_lock);
- SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.publicName());
+ ConcurrentJSLocker locker(symbolTable.m_lock);
+ SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
if (iter == symbolTable.end(locker))
return false;
SymbolTableEntry::Fast entry = iter->value;
ASSERT(!entry.isNull());
- descriptor.setDescriptor(
- object->registerAt(entry.getIndex()).get(), entry.getAttributes() | DontDelete);
+
+ ScopeOffset offset = entry.scopeOffset();
+ // Defend against the inspector asking for a var after it has been optimized out.
+ if (!object->isValidScopeOffset(offset))
+ return false;
+
+ descriptor.setDescriptor(object->variableAt(offset).get(), entry.getAttributes() | DontDelete);
return true;
}
@@ -103,77 +124,106 @@ inline bool symbolTableGet(
bool& slotIsWriteable)
{
SymbolTable& symbolTable = *object->symbolTable();
- ConcurrentJITLocker locker(symbolTable.m_lock);
- SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.publicName());
+ ConcurrentJSLocker locker(symbolTable.m_lock);
+ SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
if (iter == symbolTable.end(locker))
return false;
SymbolTableEntry::Fast entry = iter->value;
ASSERT(!entry.isNull());
- slot.setValue(object, entry.getAttributes() | DontDelete, object->registerAt(entry.getIndex()).get());
+
+ ScopeOffset offset = entry.scopeOffset();
+ // Defend against the inspector asking for a var after it has been optimized out.
+ if (!object->isValidScopeOffset(offset))
+ return false;
+
+ slot.setValue(object, entry.getAttributes() | DontDelete, object->variableAt(offset).get());
slotIsWriteable = !entry.isReadOnly();
return true;
}
template<typename SymbolTableObjectType>
-inline bool symbolTablePut(
- SymbolTableObjectType* object, ExecState* exec, PropertyName propertyName, JSValue value,
- bool shouldThrow)
+ALWAYS_INLINE void symbolTablePutTouchWatchpointSet(VM& vm, SymbolTableObjectType* object, PropertyName propertyName, JSValue value, WriteBarrierBase<Unknown>* reg, WatchpointSet* set)
+{
+ reg->set(vm, object, value);
+ if (set)
+ VariableWriteFireDetail::touch(vm, set, object, propertyName);
+}
+
+template<typename SymbolTableObjectType>
+ALWAYS_INLINE void symbolTablePutInvalidateWatchpointSet(VM& vm, SymbolTableObjectType* object, PropertyName propertyName, JSValue value, WriteBarrierBase<Unknown>* reg, WatchpointSet* set)
+{
+ reg->set(vm, object, value);
+ if (set)
+ set->invalidate(vm, VariableWriteFireDetail(object, propertyName)); // Don't mess around - if we had found this statically, we would have invalidated it.
+}
+
+enum class SymbolTablePutMode {
+ Touch,
+ Invalidate
+};
+
+template<SymbolTablePutMode symbolTablePutMode, typename SymbolTableObjectType>
+inline bool symbolTablePut(SymbolTableObjectType* object, ExecState* exec, PropertyName propertyName, JSValue value, bool shouldThrowReadOnlyError, bool ignoreReadOnlyErrors, bool& putResult)
{
VM& vm = exec->vm();
- ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(object));
-
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ WatchpointSet* set = nullptr;
WriteBarrierBase<Unknown>* reg;
{
SymbolTable& symbolTable = *object->symbolTable();
- GCSafeConcurrentJITLocker locker(symbolTable.m_lock, exec->vm().heap);
- SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.publicName());
+ // FIXME: This is very suspicious. We shouldn't need a GC-safe lock here.
+ // https://bugs.webkit.org/show_bug.cgi?id=134601
+ GCSafeConcurrentJSLocker locker(symbolTable.m_lock, vm.heap);
+ SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
if (iter == symbolTable.end(locker))
return false;
bool wasFat;
SymbolTableEntry::Fast fastEntry = iter->value.getFast(wasFat);
ASSERT(!fastEntry.isNull());
- if (fastEntry.isReadOnly()) {
- if (shouldThrow)
- throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
+ if (fastEntry.isReadOnly() && !ignoreReadOnlyErrors) {
+ if (shouldThrowReadOnlyError)
+ throwTypeError(exec, scope, ASCIILiteral(ReadonlyPropertyWriteError));
+ putResult = false;
return true;
}
- if (VariableWatchpointSet* set = iter->value.watchpointSet())
- set->notifyWrite(value);
- reg = &object->registerAt(fastEntry.getIndex());
+
+ ScopeOffset offset = fastEntry.scopeOffset();
+
+ // Defend against the inspector asking for a var after it has been optimized out.
+ if (!object->isValidScopeOffset(offset))
+ return false;
+
+ set = iter->value.watchpointSet();
+ reg = &object->variableAt(offset);
}
// 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
// locks while GC'ing.
- reg->set(vm, object, value);
+ if (symbolTablePutMode == SymbolTablePutMode::Invalidate)
+ symbolTablePutInvalidateWatchpointSet(vm, object, propertyName, value, reg, set);
+ else
+ symbolTablePutTouchWatchpointSet(vm, object, propertyName, value, reg, set);
+ putResult = true;
return true;
}
template<typename SymbolTableObjectType>
-inline bool symbolTablePutWithAttributes(
- SymbolTableObjectType* object, VM& vm, PropertyName propertyName,
- JSValue value, unsigned attributes)
+inline bool symbolTablePutTouchWatchpointSet(
+ SymbolTableObjectType* object, ExecState* exec, PropertyName propertyName, JSValue value,
+ bool shouldThrowReadOnlyError, bool ignoreReadOnlyErrors, bool& putResult)
{
ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(object));
+ return symbolTablePut<SymbolTablePutMode::Touch>(object, exec, propertyName, value, shouldThrowReadOnlyError, ignoreReadOnlyErrors, putResult);
+}
- WriteBarrierBase<Unknown>* reg;
- {
- SymbolTable& symbolTable = *object->symbolTable();
- ConcurrentJITLocker locker(symbolTable.m_lock);
- SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.publicName());
- if (iter == symbolTable.end(locker))
- return false;
- SymbolTableEntry& entry = iter->value;
- ASSERT(!entry.isNull());
- if (VariableWatchpointSet* set = entry.watchpointSet())
- set->notifyWrite(value);
- entry.setAttributes(attributes);
- reg = &object->registerAt(entry.getIndex());
- }
- reg->set(vm, object, value);
- return true;
+template<typename SymbolTableObjectType>
+inline bool symbolTablePutInvalidateWatchpointSet(
+ SymbolTableObjectType* object, ExecState* exec, PropertyName propertyName, JSValue value,
+ bool shouldThrowReadOnlyError, bool ignoreReadOnlyErrors, bool& putResult)
+{
+ ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(object));
+ return symbolTablePut<SymbolTablePutMode::Invalidate>(object, exec, propertyName, value, shouldThrowReadOnlyError, ignoreReadOnlyErrors, putResult);
}
} // namespace JSC
-
-#endif // JSSymbolTableObject_h
-