1/*
2 * Copyright (C) 2013, 2016 Apple 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. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "ArrayBufferView.h"
29#include "JSArrayBufferView.h"
30#include "JSDataView.h"
31
32namespace JSC {
33
34inline bool JSArrayBufferView::isShared()
35{
36 switch (m_mode) {
37 case WastefulTypedArray:
38 return existingBufferInButterfly()->isShared();
39 case DataViewMode:
40 return jsCast<JSDataView*>(this)->possiblySharedBuffer()->isShared();
41 default:
42 return false;
43 }
44}
45
46template<JSArrayBufferView::Requester requester>
47inline ArrayBuffer* JSArrayBufferView::possiblySharedBufferImpl()
48{
49 if (requester == ConcurrentThread)
50 ASSERT(m_mode != FastTypedArray && m_mode != OversizeTypedArray);
51
52 switch (m_mode) {
53 case WastefulTypedArray:
54 return existingBufferInButterfly();
55 case DataViewMode:
56 return jsCast<JSDataView*>(this)->possiblySharedBuffer();
57 case FastTypedArray:
58 case OversizeTypedArray:
59 return slowDownAndWasteMemory();
60 }
61 ASSERT_NOT_REACHED();
62 return nullptr;
63}
64
65inline ArrayBuffer* JSArrayBufferView::possiblySharedBuffer()
66{
67 return possiblySharedBufferImpl<Mutator>();
68}
69
70inline ArrayBuffer* JSArrayBufferView::existingBufferInButterfly()
71{
72 ASSERT(m_mode == WastefulTypedArray);
73 return butterfly()->indexingHeader()->arrayBuffer();
74}
75
76inline RefPtr<ArrayBufferView> JSArrayBufferView::unsharedImpl()
77{
78 RefPtr<ArrayBufferView> result = possiblySharedImpl();
79 RELEASE_ASSERT(!result->isShared());
80 return result;
81}
82
83template<JSArrayBufferView::Requester requester, typename ResultType>
84inline ResultType JSArrayBufferView::byteOffsetImpl()
85{
86 if (!hasArrayBuffer())
87 return 0;
88
89 if (requester == ConcurrentThread)
90 WTF::loadLoadFence();
91
92 ArrayBuffer* buffer = possiblySharedBufferImpl<requester>();
93 if (requester == Mutator) {
94 ASSERT(!isCompilationThread());
95 ASSERT(!vector() == !buffer->data());
96 }
97
98 ptrdiff_t delta =
99 bitwise_cast<uint8_t*>(vector()) - static_cast<uint8_t*>(buffer->data());
100
101 unsigned result = static_cast<unsigned>(delta);
102 if (requester == Mutator)
103 ASSERT(static_cast<ptrdiff_t>(result) == delta);
104 else {
105 if (static_cast<ptrdiff_t>(result) != delta)
106 return { };
107 }
108
109 return result;
110}
111
112inline unsigned JSArrayBufferView::byteOffset()
113{
114 return byteOffsetImpl<Mutator, unsigned>();
115}
116
117inline Optional<unsigned> JSArrayBufferView::byteOffsetConcurrently()
118{
119 return byteOffsetImpl<ConcurrentThread, Optional<unsigned>>();
120}
121
122inline RefPtr<ArrayBufferView> JSArrayBufferView::toWrapped(VM& vm, JSValue value)
123{
124 if (JSArrayBufferView* view = jsDynamicCast<JSArrayBufferView*>(vm, value)) {
125 if (!view->isShared())
126 return view->unsharedImpl();
127 }
128 return nullptr;
129}
130
131} // namespace JSC
132