]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/JSSymbolTableObject.h
JavaScriptCore-7600.1.4.17.5.tar.gz
[apple/javascriptcore.git] / runtime / JSSymbolTableObject.h
index 6db2b88abc0102b1326809905ebd9283e2fce688..ecdd8a0a705ad87ff8653182a861ed0964f8cd5b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2014 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. 
  *
@@ -32,6 +32,7 @@
 #include "JSScope.h"
 #include "PropertyDescriptor.h"
 #include "SymbolTable.h"
+#include "VariableWatchpointSetInlines.h"
 
 namespace JSC {
 
@@ -39,9 +40,7 @@ class JSSymbolTableObject : public JSScope {
 public:
     typedef JSScope Base;
     
-    SharedSymbolTable* symbolTable() const { return m_symbolTable.get(); }
-    
-    static NO_RETURN_DUE_TO_CRASH void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
+    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);
@@ -49,7 +48,7 @@ public:
 protected:
     static const unsigned StructureFlags = IsEnvironmentRecord | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags;
     
-    JSSymbolTableObject(VM& vm, Structure* structure, JSScope* scope, SharedSymbolTable* symbolTable = 0)
+    JSSymbolTableObject(VM& vm, Structure* structure, JSScope* scope, SymbolTable* symbolTable = 0)
         : Base(vm, structure, scope)
     {
         if (symbolTable)
@@ -60,12 +59,12 @@ protected:
     {
         Base::finishCreation(vm);
         if (!m_symbolTable)
-            m_symbolTable.set(vm, this, SharedSymbolTable::create(vm));
+            m_symbolTable.set(vm, this, SymbolTable::create(vm));
     }
 
     static void visitChildren(JSCell*, SlotVisitor&);
 
-    WriteBarrier<SharedSymbolTable> m_symbolTable;
+    WriteBarrier<SymbolTable> m_symbolTable;
 };
 
 template<typename SymbolTableObjectType>
@@ -73,12 +72,13 @@ inline bool symbolTableGet(
     SymbolTableObjectType* object, PropertyName propertyName, PropertySlot& slot)
 {
     SymbolTable& symbolTable = *object->symbolTable();
-    SymbolTable::iterator iter = symbolTable.find(propertyName.publicName());
-    if (iter == symbolTable.end())
+    ConcurrentJITLocker 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->registerAt(entry.getIndex()).get());
+    slot.setValue(object, entry.getAttributes() | DontDelete, object->registerAt(entry.getIndex()).get());
     return true;
 }
 
@@ -87,8 +87,9 @@ inline bool symbolTableGet(
     SymbolTableObjectType* object, PropertyName propertyName, PropertyDescriptor& descriptor)
 {
     SymbolTable& symbolTable = *object->symbolTable();
-    SymbolTable::iterator iter = symbolTable.find(propertyName.publicName());
-    if (iter == symbolTable.end())
+    ConcurrentJITLocker 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());
@@ -103,12 +104,13 @@ inline bool symbolTableGet(
     bool& slotIsWriteable)
 {
     SymbolTable& symbolTable = *object->symbolTable();
-    SymbolTable::iterator iter = symbolTable.find(propertyName.publicName());
-    if (iter == symbolTable.end())
+    ConcurrentJITLocker 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->registerAt(entry.getIndex()).get());
+    slot.setValue(object, entry.getAttributes() | DontDelete, object->registerAt(entry.getIndex()).get());
     slotIsWriteable = !entry.isReadOnly();
     return true;
 }
@@ -121,21 +123,34 @@ inline bool symbolTablePut(
     VM& vm = exec->vm();
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(object));
     
-    SymbolTable& symbolTable = *object->symbolTable();
-    SymbolTable::iterator iter = symbolTable.find(propertyName.publicName());
-    if (iter == symbolTable.end())
-        return false;
-    bool wasFat;
-    SymbolTableEntry::Fast fastEntry = iter->value.getFast(wasFat);
-    ASSERT(!fastEntry.isNull());
-    if (fastEntry.isReadOnly()) {
-        if (shouldThrow)
-            throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
-        return true;
+    WriteBarrierBase<Unknown>* reg;
+    {
+        SymbolTable& symbolTable = *object->symbolTable();
+        // FIXME: This is very suspicious. We shouldn't need a GC-safe lock here.
+        // https://bugs.webkit.org/show_bug.cgi?id=134601
+        GCSafeConcurrentJITLocker locker(symbolTable.m_lock, exec->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);
+            return true;
+        }
+        if (VariableWatchpointSet* set = iter->value.watchpointSet()) {
+            // FIXME: It's strange that we're doing this while holding the symbol table's lock.
+            // https://bugs.webkit.org/show_bug.cgi?id=134601
+            set->notifyWrite(vm, value);
+        }
+        reg = &object->registerAt(fastEntry.getIndex());
     }
-    if (UNLIKELY(wasFat))
-        iter->value.notifyWrite();
-    object->registerAt(fastEntry.getIndex()).set(vm, object, value);
+    // 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);
     return true;
 }
 
@@ -145,15 +160,22 @@ inline bool symbolTablePutWithAttributes(
     JSValue value, unsigned attributes)
 {
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(object));
-    
-    SymbolTable::iterator iter = object->symbolTable()->find(propertyName.publicName());
-    if (iter == object->symbolTable()->end())
-        return false;
-    SymbolTableEntry& entry = iter->value;
-    ASSERT(!entry.isNull());
-    entry.notifyWrite();
-    entry.setAttributes(attributes);
-    object->registerAt(entry.getIndex()).set(vm, object, value);
+
+    WriteBarrierBase<Unknown>* reg;
+    {
+        SymbolTable& symbolTable = *object->symbolTable();
+        ConcurrentJITLocker locker(symbolTable.m_lock);
+        SymbolTable::Map::iterator iter = symbolTable.find(locker, propertyName.uid());
+        if (iter == symbolTable.end(locker))
+            return false;
+        SymbolTableEntry& entry = iter->value;
+        ASSERT(!entry.isNull());
+        if (VariableWatchpointSet* set = entry.watchpointSet())
+            set->notifyWrite(vm, value);
+        entry.setAttributes(attributes);
+        reg = &object->registerAt(entry.getIndex());
+    }
+    reg->set(vm, object, value);
     return true;
 }