Home | History | Annotate | Download | only in v8
      1 /*
      2  * Copyright (C) 2009 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "bindings/v8/V8ValueCache.h"
     28 
     29 #include "bindings/v8/V8Binding.h"
     30 #include "wtf/text/StringHash.h"
     31 
     32 namespace WebCore {
     33 
     34 StringCacheMapTraits::MapType* StringCacheMapTraits::MapFromWeakCallbackData(
     35     const v8::WeakCallbackData<v8::String, WeakCallbackDataType>& data)
     36 {
     37     return &(V8PerIsolateData::from(data.GetIsolate())->stringCache()->m_stringCache);
     38 }
     39 
     40 
     41 void StringCacheMapTraits::Dispose(
     42     v8::Isolate* isolate, v8::UniquePersistent<v8::String> value, StringImpl* key)
     43 {
     44     V8PerIsolateData::from(isolate)->stringCache()->InvalidateLastString();
     45     key->deref();
     46 }
     47 
     48 
     49 StringCache::~StringCache()
     50 {
     51     // The MapType::Dispose callback calls StringCache::InvalidateLastString,
     52     // which will only work while the destructor has not yet finished. Thus,
     53     // we need to clear the map before the destructor has completed.
     54     m_stringCache.Clear();
     55 }
     56 
     57 static v8::Local<v8::String> makeExternalString(const String& string, v8::Isolate* isolate)
     58 {
     59     if (string.is8Bit()) {
     60         WebCoreStringResource8* stringResource = new WebCoreStringResource8(string);
     61         v8::Local<v8::String> newString = v8::String::NewExternal(isolate, stringResource);
     62         if (newString.IsEmpty())
     63             delete stringResource;
     64         return newString;
     65     }
     66 
     67     WebCoreStringResource16* stringResource = new WebCoreStringResource16(string);
     68     v8::Local<v8::String> newString = v8::String::NewExternal(isolate, stringResource);
     69     if (newString.IsEmpty())
     70         delete stringResource;
     71     return newString;
     72 }
     73 
     74 v8::Handle<v8::String> StringCache::v8ExternalStringSlow(StringImpl* stringImpl, v8::Isolate* isolate)
     75 {
     76     if (!stringImpl->length())
     77         return v8::String::Empty(isolate);
     78 
     79     StringCacheMapTraits::MapType::PersistentValueReference cachedV8String = m_stringCache.GetReference(stringImpl);
     80     if (!cachedV8String.IsEmpty()) {
     81         m_lastStringImpl = stringImpl;
     82         m_lastV8String = cachedV8String;
     83         return m_lastV8String.NewLocal(isolate);
     84     }
     85 
     86     return createStringAndInsertIntoCache(stringImpl, isolate);
     87 }
     88 
     89 void StringCache::setReturnValueFromStringSlow(v8::ReturnValue<v8::Value> returnValue, StringImpl* stringImpl)
     90 {
     91     if (!stringImpl->length()) {
     92         returnValue.SetEmptyString();
     93         return;
     94     }
     95 
     96     StringCacheMapTraits::MapType::PersistentValueReference cachedV8String = m_stringCache.GetReference(stringImpl);
     97     if (!cachedV8String.IsEmpty()) {
     98         m_lastStringImpl = stringImpl;
     99         m_lastV8String = cachedV8String;
    100         m_lastV8String.SetReturnValue(returnValue);
    101         return;
    102     }
    103 
    104     returnValue.Set(createStringAndInsertIntoCache(stringImpl, returnValue.GetIsolate()));
    105 }
    106 
    107 v8::Local<v8::String> StringCache::createStringAndInsertIntoCache(StringImpl* stringImpl, v8::Isolate* isolate)
    108 {
    109     ASSERT(!m_stringCache.Contains(stringImpl));
    110     ASSERT(stringImpl->length());
    111 
    112     v8::Local<v8::String> newString = makeExternalString(String(stringImpl), isolate);
    113     if (newString.IsEmpty())
    114         return newString;
    115 
    116     v8::UniquePersistent<v8::String> wrapper(isolate, newString);
    117 
    118     stringImpl->ref();
    119     wrapper.MarkIndependent();
    120     m_stringCache.Set(stringImpl, wrapper.Pass(), &m_lastV8String);
    121     m_lastStringImpl = stringImpl;
    122 
    123     return newString;
    124 }
    125 
    126 void StringCache::InvalidateLastString()
    127 {
    128     m_lastStringImpl = nullptr;
    129     m_lastV8String.Reset();
    130 }
    131 
    132 } // namespace WebCore
    133