1/*
2 * Copyright (C) 2018-2019 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 "JSCast.h"
29#include "ParserModes.h"
30#include "VariableEnvironment.h"
31#include <wtf/HashMap.h>
32#include <wtf/MallocPtr.h>
33
34namespace JSC {
35
36class BytecodeCacheError;
37class CachedBytecode;
38class SourceCodeKey;
39class UnlinkedCodeBlock;
40class UnlinkedFunctionCodeBlock;
41
42enum class SourceCodeType;
43
44// This struct has to be updated when incrementally writing to the bytecode
45// cache, since this will only be filled in when we parse the function
46struct CachedFunctionExecutableMetadata {
47 CodeFeatures m_features;
48 bool m_hasCapturedVariables;
49};
50
51struct CachedFunctionExecutableOffsets {
52 static ptrdiff_t codeBlockForCallOffset();
53 static ptrdiff_t codeBlockForConstructOffset();
54 static ptrdiff_t metadataOffset();
55};
56
57struct CachedWriteBarrierOffsets {
58 static ptrdiff_t ptrOffset();
59};
60
61struct CachedPtrOffsets {
62 static ptrdiff_t offsetOffset();
63};
64
65class VariableLengthObjectBase {
66 friend class CachedBytecode;
67
68protected:
69 VariableLengthObjectBase(ptrdiff_t offset)
70 : m_offset(offset)
71 {
72 }
73
74 ptrdiff_t m_offset;
75};
76
77class Decoder : public RefCounted<Decoder> {
78 WTF_MAKE_NONCOPYABLE(Decoder);
79
80public:
81 static Ref<Decoder> create(VM&, Ref<CachedBytecode>, RefPtr<SourceProvider> = nullptr);
82
83 ~Decoder();
84
85 VM& vm() { return m_vm; }
86 size_t size() const;
87
88 ptrdiff_t offsetOf(const void*);
89 void cacheOffset(ptrdiff_t, void*);
90 WTF::Optional<void*> cachedPtrForOffset(ptrdiff_t);
91 const void* ptrForOffsetFromBase(ptrdiff_t);
92 CompactVariableMap::Handle handleForEnvironment(CompactVariableEnvironment*) const;
93 void setHandleForEnvironment(CompactVariableEnvironment*, const CompactVariableMap::Handle&);
94 void addLeafExecutable(const UnlinkedFunctionExecutable*, ptrdiff_t);
95 RefPtr<SourceProvider> provider() const;
96
97 template<typename Functor>
98 void addFinalizer(const Functor&);
99
100private:
101 Decoder(VM&, Ref<CachedBytecode>, RefPtr<SourceProvider>);
102
103 VM& m_vm;
104 Ref<CachedBytecode> m_cachedBytecode;
105 HashMap<ptrdiff_t, void*> m_offsetToPtrMap;
106 Vector<std::function<void()>> m_finalizers;
107 HashMap<CompactVariableEnvironment*, CompactVariableMap::Handle> m_environmentToHandleMap;
108 RefPtr<SourceProvider> m_provider;
109};
110
111JS_EXPORT_PRIVATE RefPtr<CachedBytecode> encodeCodeBlock(VM&, const SourceCodeKey&, const UnlinkedCodeBlock*);
112JS_EXPORT_PRIVATE RefPtr<CachedBytecode> encodeCodeBlock(VM&, const SourceCodeKey&, const UnlinkedCodeBlock*, int fd, BytecodeCacheError&);
113
114UnlinkedCodeBlock* decodeCodeBlockImpl(VM&, const SourceCodeKey&, Ref<CachedBytecode>);
115
116template<typename UnlinkedCodeBlockType>
117UnlinkedCodeBlockType* decodeCodeBlock(VM& vm, const SourceCodeKey& key, Ref<CachedBytecode> cachedBytecode)
118{
119 return jsCast<UnlinkedCodeBlockType*>(decodeCodeBlockImpl(vm, key, WTFMove(cachedBytecode)));
120}
121
122JS_EXPORT_PRIVATE RefPtr<CachedBytecode> encodeFunctionCodeBlock(VM&, const UnlinkedFunctionCodeBlock*, BytecodeCacheError&);
123
124JS_EXPORT_PRIVATE void decodeFunctionCodeBlock(Decoder&, int32_t cachedFunctionCodeBlockOffset, WriteBarrier<UnlinkedFunctionCodeBlock>&, const JSCell*);
125
126bool isCachedBytecodeStillValid(VM&, Ref<CachedBytecode>, const SourceCodeKey&, SourceCodeType);
127
128} // namespace JSC
129