summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/Identifier.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
commit32761a6cee1d0dee366b885b7b9c777e67885688 (patch)
treed6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/runtime/Identifier.cpp
parenta4e969f4965059196ca948db781e52f7cfebf19e (diff)
downloadWebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/runtime/Identifier.cpp')
-rw-r--r--Source/JavaScriptCore/runtime/Identifier.cpp126
1 files changed, 103 insertions, 23 deletions
diff --git a/Source/JavaScriptCore/runtime/Identifier.cpp b/Source/JavaScriptCore/runtime/Identifier.cpp
index d26d9567c..3658d8772 100644
--- a/Source/JavaScriptCore/runtime/Identifier.cpp
+++ b/Source/JavaScriptCore/runtime/Identifier.cpp
@@ -25,7 +25,7 @@
#include "JSObject.h"
#include "JSScope.h"
#include "NumericStrings.h"
-#include "JSCInlines.h"
+#include "Operations.h"
#include <new>
#include <string.h>
#include <wtf/Assertions.h>
@@ -38,33 +38,121 @@ using WTF::ThreadSpecific;
namespace JSC {
-Ref<StringImpl> Identifier::add(VM* vm, const char* c)
+IdentifierTable* createIdentifierTable()
+{
+ return new IdentifierTable;
+}
+
+void deleteIdentifierTable(IdentifierTable* table)
+{
+ delete table;
+}
+
+struct IdentifierASCIIStringTranslator {
+ static unsigned hash(const LChar* c)
+ {
+ return StringHasher::computeHashAndMaskTop8Bits(c);
+ }
+
+ static bool equal(StringImpl* r, const LChar* s)
+ {
+ return Identifier::equal(r, s);
+ }
+
+ static void translate(StringImpl*& location, const LChar* c, unsigned hash)
+ {
+ size_t length = strlen(reinterpret_cast<const char*>(c));
+ location = &StringImpl::createFromLiteral(reinterpret_cast<const char*>(c), length).leakRef();
+ location->setHash(hash);
+ }
+};
+
+struct IdentifierLCharFromUCharTranslator {
+ static unsigned hash(const CharBuffer<UChar>& buf)
+ {
+ return StringHasher::computeHashAndMaskTop8Bits(buf.s, buf.length);
+ }
+
+ static bool equal(StringImpl* str, const CharBuffer<UChar>& buf)
+ {
+ return Identifier::equal(str, buf.s, buf.length);
+ }
+
+ static void translate(StringImpl*& location, const CharBuffer<UChar>& buf, unsigned hash)
+ {
+ LChar* d;
+ StringImpl& r = StringImpl::createUninitialized(buf.length, d).leakRef();
+ WTF::copyLCharsFromUCharSource(d, buf.s, buf.length);
+ r.setHash(hash);
+ location = &r;
+ }
+};
+
+PassRefPtr<StringImpl> Identifier::add(VM* vm, const char* c)
{
ASSERT(c);
ASSERT(c[0]);
if (!c[1])
- return *vm->smallStrings.singleCharacterStringRep(c[0]);
+ return add(vm, vm->smallStrings.singleCharacterStringRep(c[0]));
+
+ IdentifierTable& identifierTable = *vm->identifierTable;
+
+ HashSet<StringImpl*>::AddResult addResult = identifierTable.add<const LChar*, IdentifierASCIIStringTranslator>(reinterpret_cast<const LChar*>(c));
+
+ // If the string is newly-translated, then we need to adopt it.
+ // The boolean in the pair tells us if that is so.
+ RefPtr<StringImpl> addedString = addResult.isNewEntry ? adoptRef(*addResult.iterator) : *addResult.iterator;
- return *AtomicStringImpl::add(c);
+ return addedString.release();
}
-Ref<StringImpl> Identifier::add(ExecState* exec, const char* c)
+PassRefPtr<StringImpl> Identifier::add(ExecState* exec, const char* c)
{
return add(&exec->vm(), c);
}
-Ref<StringImpl> Identifier::add8(VM* vm, const UChar* s, int length)
+PassRefPtr<StringImpl> Identifier::add8(VM* vm, const UChar* s, int length)
{
if (length == 1) {
UChar c = s[0];
ASSERT(c <= 0xff);
if (canUseSingleCharacterString(c))
- return *vm->smallStrings.singleCharacterStringRep(c);
+ return add(vm, vm->smallStrings.singleCharacterStringRep(c));
}
+
if (!length)
- return *StringImpl::empty();
+ return StringImpl::empty();
+ CharBuffer<UChar> buf = { s, static_cast<unsigned>(length) };
+ HashSet<StringImpl*>::AddResult addResult = vm->identifierTable->add<CharBuffer<UChar>, IdentifierLCharFromUCharTranslator >(buf);
+
+ // If the string is newly-translated, then we need to adopt it.
+ // The boolean in the pair tells us if that is so.
+ return addResult.isNewEntry ? adoptRef(*addResult.iterator) : *addResult.iterator;
+}
+
+PassRefPtr<StringImpl> Identifier::addSlowCase(VM* vm, StringImpl* r)
+{
+ if (r->isEmptyUnique())
+ return r;
+ ASSERT(!r->isIdentifier());
+ // The empty & null strings are static singletons, and static strings are handled
+ // in ::add() in the header, so we should never get here with a zero length string.
+ ASSERT(r->length());
+
+ if (r->length() == 1) {
+ UChar c = (*r)[0];
+ if (c <= maxSingleCharacterString)
+ r = vm->smallStrings.singleCharacterStringRep(c);
+ if (r->isIdentifier())
+ return r;
+ }
+
+ return *vm->identifierTable->add(r).iterator;
+}
- return *AtomicStringImpl::add(s, length);
+PassRefPtr<StringImpl> Identifier::addSlowCase(ExecState* exec, StringImpl* r)
+{
+ return addSlowCase(&exec->vm(), r);
}
Identifier Identifier::from(ExecState* exec, unsigned value)
@@ -97,34 +185,26 @@ Identifier Identifier::from(VM* vm, double value)
return Identifier(vm, vm->numericStrings.add(value));
}
-void Identifier::dump(PrintStream& out) const
-{
- if (impl())
- out.print(impl());
- else
- out.print("<null identifier>");
-}
-
#ifndef NDEBUG
-void Identifier::checkCurrentAtomicStringTable(VM* vm)
+void Identifier::checkCurrentIdentifierTable(VM* vm)
{
// Check the identifier table accessible through the threadspecific matches the
// vm's identifier table.
- ASSERT_UNUSED(vm, vm->atomicStringTable() == wtfThreadData().atomicStringTable());
+ ASSERT_UNUSED(vm, vm->identifierTable == wtfThreadData().currentIdentifierTable());
}
-void Identifier::checkCurrentAtomicStringTable(ExecState* exec)
+void Identifier::checkCurrentIdentifierTable(ExecState* exec)
{
- checkCurrentAtomicStringTable(&exec->vm());
+ checkCurrentIdentifierTable(&exec->vm());
}
#else
// These only exists so that our exports are the same for debug and release builds.
// This would be an RELEASE_ASSERT_NOT_REACHED(), but we're in NDEBUG only code here!
-NO_RETURN_DUE_TO_CRASH void Identifier::checkCurrentAtomicStringTable(VM*) { CRASH(); }
-NO_RETURN_DUE_TO_CRASH void Identifier::checkCurrentAtomicStringTable(ExecState*) { CRASH(); }
+NO_RETURN_DUE_TO_CRASH void Identifier::checkCurrentIdentifierTable(VM*) { CRASH(); }
+NO_RETURN_DUE_TO_CRASH void Identifier::checkCurrentIdentifierTable(ExecState*) { CRASH(); }
#endif