Chromium Code Reviews| Index: src/elements.cc |
| diff --git a/src/elements.cc b/src/elements.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ff00e94f26260e8cde3a25d6ad02dfea129340d0 |
| --- /dev/null |
| +++ b/src/elements.cc |
| @@ -0,0 +1,297 @@ |
| +// Copyright 2011 the V8 project authors. All rights reserved. |
| +// Redistribution and use in source and binary forms, with or without |
| +// modification, are permitted provided that the following conditions are |
| +// met: |
| +// |
| +// * Redistributions of source code must retain the above copyright |
| +// notice, this list of conditions and the following disclaimer. |
| +// * 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. |
| +// * Neither the name of Google Inc. nor the names of its |
| +// contributors may be used to endorse or promote products derived |
| +// from this software without specific prior written permission. |
| +// |
| +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| +// "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 THE COPYRIGHT |
| +// OWNER 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 "v8.h" |
| + |
| +#include "objects.h" |
| +#include "elements.h" |
| + |
| +namespace v8 { |
| +namespace internal { |
| + |
| + |
| +// Base class for element handler implementations. Contains the |
| +// the common logic for objects with different ElementsKinds. |
| +// Subclasses must specialize method for which the element |
| +// implementation differs from the base class implementation. |
| +// |
| +// This class is intended to be used in the following way: |
| +// |
| +// class SomeElementsHandlerImpl : |
| +// public ElementsHandlerImpl<SomeElementsHandlerImpl> { |
|
Jakob Kummerow
2011/07/30 10:29:21
nit: second template argument (BackingStoreClass)
danno
2011/07/30 13:10:10
Done.
|
| +// ... |
| +// } |
| +// |
| +// This is an example of Curiously recurring template pattern |
| +// (see http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). |
| +// We use CRTP to guarantee aggressive compile time optimizations (i.e. |
| +// inlining and specialization of SomeElementsHandlerImpl methods). |
| +template <typename ConcreteHandlerImpl, typename BackingStoreClass> |
| +class ElementsHandlerImpl { |
| + public: |
| + static MaybeObject* GetWithReceiver(JSObject* obj, |
| + Object* receiver, |
| + uint32_t index) { |
| + if (index < ConcreteHandlerImpl::GetLength(obj)) { |
| + BackingStoreClass* backing_store = |
| + ElementsHandlerImpl::GetBackingStore(obj); |
| + MaybeObject* result = backing_store->get(index); |
| + if (!result->IsTheHole()) return result; |
| + } |
| + |
| + Object* pt = obj->GetPrototype(); |
| + Heap* heap = obj->GetHeap(); |
| + if (pt == heap->null_value()) return heap->undefined_value(); |
| + return pt->GetElementWithReceiver(receiver, index); |
| + } |
| + |
| + protected: |
| + static BackingStoreClass* GetBackingStore(JSObject* obj) { |
| + return BackingStoreClass::cast(obj->elements()); |
| + } |
| + |
| + static uint32_t GetLength(JSObject* obj) { |
| + return ConcreteHandlerImpl::GetBackingStore(obj)->length(); |
| + } |
| + |
| + private: |
| + DISALLOW_IMPLICIT_CONSTRUCTORS(ElementsHandlerImpl); |
| +}; |
| + |
| + |
| +class FastElementsHandlerImpl |
| + : public ElementsHandlerImpl< FastElementsHandlerImpl, FixedArray> { |
|
Jakob Kummerow
2011/07/30 10:29:21
nit: extra space
danno
2011/07/30 13:10:10
Done.
|
| +}; |
| + |
| + |
| +class FastDoubleElementsHandlerImpl |
| + : public ElementsHandlerImpl<FastDoubleElementsHandlerImpl, |
| + FixedDoubleArray> { |
| +}; |
| + |
| + |
| +// Super class for all external element arrays, whose handler implementation is |
| +// identical except for specialization. |
| +template<typename ConcreteExternalElementHandlerImpl, |
| + typename ExternalArray> |
| +class ExternalElementsHandlerImpl |
| + : public ElementsHandlerImpl<ConcreteExternalElementHandlerImpl, |
| + ExternalArray> { |
| +}; |
| + |
| + |
| +class ExternalByteElementsHandlerImpl |
| + : public ExternalElementsHandlerImpl<ExternalByteElementsHandlerImpl, |
| + ExternalByteArray> { |
| +}; |
| + |
| + |
| +class ExternalUnsignedByteElementsHandlerImpl |
| + : public ExternalElementsHandlerImpl< |
| + ExternalUnsignedByteElementsHandlerImpl, ExternalUnsignedByteArray> { |
| +}; |
| + |
| + |
| +class ExternalShortElementsHandlerImpl |
| + : public ExternalElementsHandlerImpl<ExternalShortElementsHandlerImpl, |
| + ExternalShortArray> { |
| +}; |
| + |
| + |
| +class ExternalUnsignedShortElementsHandlerImpl |
| + : public ExternalElementsHandlerImpl< |
| + ExternalUnsignedShortElementsHandlerImpl, ExternalUnsignedShortArray> { |
| +}; |
| + |
| + |
| +class ExternalIntElementsHandlerImpl |
| + : public ExternalElementsHandlerImpl<ExternalIntElementsHandlerImpl, |
| + ExternalIntArray> { |
| +}; |
| + |
| + |
| +class ExternalUnsignedIntElementsHandlerImpl |
| + : public ExternalElementsHandlerImpl<ExternalUnsignedIntElementsHandlerImpl, |
| + ExternalUnsignedIntArray> { |
| +}; |
| + |
| + |
| +class ExternalFloatElementsHandlerImpl |
| + : public ExternalElementsHandlerImpl<ExternalFloatElementsHandlerImpl, |
| + ExternalFloatArray> { |
| +}; |
| + |
| + |
| +class ExternalDoubleElementsHandlerImpl |
| + : public ExternalElementsHandlerImpl<ExternalDoubleElementsHandlerImpl, |
| + ExternalDoubleArray> { |
| +}; |
| + |
| + |
| +class PixelElementsHandlerImpl |
| + : public ExternalElementsHandlerImpl<PixelElementsHandlerImpl, |
| + ExternalPixelArray> { |
| +}; |
| + |
| + |
| +class DictionaryElementsHandlerImpl |
| + : public ElementsHandlerImpl<DictionaryElementsHandlerImpl, |
| + NumberDictionary> { |
| + public: |
| + static MaybeObject* GetNumberDictionaryElement( |
| + JSObject* obj, |
| + Object* receiver, |
| + NumberDictionary* backing_store, |
| + uint32_t index) { |
| + int entry = backing_store->FindEntry(index); |
| + if (entry != NumberDictionary::kNotFound) { |
| + Object* element = backing_store->ValueAt(entry); |
| + PropertyDetails details = backing_store->DetailsAt(entry); |
| + if (details.type() == CALLBACKS) { |
| + return obj->GetElementWithCallback(receiver, |
| + element, |
| + index, |
| + obj); |
| + } |
| + return element; |
| + } |
| + return obj->GetHeap()->the_hole_value(); |
| + } |
| + |
| + static MaybeObject* GetWithReceiver(JSObject* obj, |
| + Object* receiver, |
| + uint32_t index) { |
| + NumberDictionary* backing_store = GetBackingStore(obj); |
| + return GetNumberDictionaryElement(obj, receiver, backing_store, index); |
| + } |
| + |
| + protected: |
| + static NumberDictionary* GetBackingStore(JSObject* obj) { |
| + return NumberDictionary::cast(obj->element_dictionary()); |
| + } |
| +}; |
| + |
| + |
| +class NonStrictArgumentsElementsHandlerImpl |
| + : public ElementsHandlerImpl<NonStrictArgumentsElementsHandlerImpl, |
| + FixedArray> { |
| + public: |
| + static MaybeObject* GetWithReceiver(JSObject* obj, |
| + Object* receiver, |
| + uint32_t index) { |
| + FixedArray* parameter_map = GetBackingStore(obj); |
| + uint32_t length = parameter_map->length(); |
| + Object* probe = |
| + (index < length - 2) ? parameter_map->get(index + 2) : NULL; |
| + if (probe != NULL && !probe->IsTheHole()) { |
| + Context* context = Context::cast(parameter_map->get(0)); |
| + int context_index = Smi::cast(probe)->value(); |
| + ASSERT(!context->get(context_index)->IsTheHole()); |
| + return context->get(context_index); |
| + } else { |
| + // Object is not mapped, defer to the arguments. |
| + FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| + if (arguments->IsDictionary()) { |
| + return DictionaryElementsHandlerImpl::GetNumberDictionaryElement( |
| + obj, |
| + receiver, |
| + NumberDictionary::cast(arguments), |
| + index); |
| + } else if (index < static_cast<uint32_t>(arguments->length())) { |
| + return arguments->get(index); |
| + } |
| + } |
| + return obj->GetHeap()->the_hole_value(); |
| + } |
| +}; |
| + |
| + |
| +template<typename Impl> |
| +class ConcreteElementsHandler : public ElementsHandler { |
| + public: |
| + ConcreteElementsHandler() {} |
| + |
| + virtual MaybeObject* GetWithReceiver(JSObject* obj, |
| + Object* receiver, |
| + uint32_t index) { |
| + return Impl::GetWithReceiver(obj, |
| + receiver, |
| + index); |
| + } |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(ConcreteElementsHandler); |
| +}; |
| + |
| + |
| +struct ConcreteElementHandlers { |
|
Jakob Kummerow
2011/07/30 10:29:21
nit: for consistency, change order to match elemen
danno
2011/07/30 13:10:10
Done.
|
| + ConcreteElementsHandler<FastElementsHandlerImpl> |
| + fast_elements_handler; |
| + ConcreteElementsHandler<FastDoubleElementsHandlerImpl> |
| + fast_double_elements_handler; |
| + ConcreteElementsHandler<ExternalByteElementsHandlerImpl> |
| + byte_elements_handler; |
| + ConcreteElementsHandler<ExternalUnsignedByteElementsHandlerImpl> |
| + unsigned_byte_elements_handler; |
| + ConcreteElementsHandler<ExternalShortElementsHandlerImpl> |
| + short_elements_handler; |
| + ConcreteElementsHandler<ExternalUnsignedShortElementsHandlerImpl> |
| + unsigned_short_elements_handler; |
| + ConcreteElementsHandler<ExternalIntElementsHandlerImpl> |
| + int_elements_handler; |
| + ConcreteElementsHandler<ExternalUnsignedIntElementsHandlerImpl> |
| + unsigned_int_elements_handler; |
| + ConcreteElementsHandler<ExternalFloatElementsHandlerImpl> |
| + float_elements_handler; |
| + ConcreteElementsHandler<ExternalDoubleElementsHandlerImpl> |
| + double_elements_handler; |
| + ConcreteElementsHandler<PixelElementsHandlerImpl> |
| + pixel_elements_handler; |
| + ConcreteElementsHandler<DictionaryElementsHandlerImpl> |
| + dictionary_elements_handler; |
| + ConcreteElementsHandler<NonStrictArgumentsElementsHandlerImpl> |
| + non_strict_arguments_elements_handler; |
| +} element_handlers; |
| + |
| + |
| +ElementsHandler* ElementsHandler::elements_handler_table_[] = { |
| + &element_handlers.fast_elements_handler, |
| + &element_handlers.fast_double_elements_handler, |
| + &element_handlers.dictionary_elements_handler, |
| + &element_handlers.non_strict_arguments_elements_handler, |
| + &element_handlers.byte_elements_handler, |
| + &element_handlers.unsigned_byte_elements_handler, |
| + &element_handlers.short_elements_handler, |
| + &element_handlers.unsigned_short_elements_handler, |
| + &element_handlers.int_elements_handler, |
| + &element_handlers.unsigned_int_elements_handler, |
| + &element_handlers.float_elements_handler, |
| + &element_handlers.double_elements_handler, |
| + &element_handlers.pixel_elements_handler |
| +}; |
| + |
| + |
| +} } // namespace v8::internal |