]> git.saurik.com Git - apple/javascriptcore.git/blob - bytecode/UnlinkedInstructionStream.h
JavaScriptCore-7600.1.4.11.8.tar.gz
[apple/javascriptcore.git] / bytecode / UnlinkedInstructionStream.h
1 /*
2 * Copyright (C) 2014 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
27 #ifndef UnlinkedInstructionStream_h
28 #define UnlinkedInstructionStream_h
29
30 #include "UnlinkedCodeBlock.h"
31 #include <wtf/RefCountedArray.h>
32
33 namespace JSC {
34
35 class UnlinkedInstructionStream {
36 WTF_MAKE_FAST_ALLOCATED;
37 public:
38 explicit UnlinkedInstructionStream(const Vector<UnlinkedInstruction>&);
39
40 unsigned count() const { return m_instructionCount; }
41
42 class Reader {
43 public:
44 explicit Reader(const UnlinkedInstructionStream&);
45
46 const UnlinkedInstruction* next();
47 bool atEnd() const { return m_index == m_stream.m_data.size(); }
48
49 private:
50 unsigned char read8();
51 unsigned read32();
52
53 const UnlinkedInstructionStream& m_stream;
54 UnlinkedInstruction m_unpackedBuffer[16];
55 unsigned m_index;
56 };
57
58 #ifndef NDEBUG
59 const RefCountedArray<UnlinkedInstruction>& unpackForDebugging() const;
60 #endif
61
62 private:
63 friend class Reader;
64
65 #ifndef NDEBUG
66 mutable RefCountedArray<UnlinkedInstruction> m_unpackedInstructionsForDebugging;
67 #endif
68
69 RefCountedArray<unsigned char> m_data;
70 unsigned m_instructionCount;
71 };
72
73 // Unlinked instructions are packed in a simple stream format.
74 //
75 // The first byte is always the opcode.
76 // It's followed by an opcode-dependent number of argument values.
77 // The first 3 bits of each value determines the format:
78 //
79 // 5-bit positive integer (1 byte total)
80 // 5-bit negative integer (1 byte total)
81 // 13-bit positive integer (2 bytes total)
82 // 13-bit negative integer (2 bytes total)
83 // 5-bit constant register index, based at 0x40000000 (1 byte total)
84 // 13-bit constant register index, based at 0x40000000 (2 bytes total)
85 // 32-bit raw value (5 bytes total)
86
87 enum PackedValueType {
88 Positive5Bit = 0,
89 Negative5Bit,
90 Positive13Bit,
91 Negative13Bit,
92 ConstantRegister5Bit,
93 ConstantRegister13Bit,
94 Full32Bit
95 };
96
97 ALWAYS_INLINE UnlinkedInstructionStream::Reader::Reader(const UnlinkedInstructionStream& stream)
98 : m_stream(stream)
99 , m_index(0)
100 {
101 }
102
103 ALWAYS_INLINE unsigned char UnlinkedInstructionStream::Reader::read8()
104 {
105 return m_stream.m_data.data()[m_index++];
106 }
107
108 ALWAYS_INLINE unsigned UnlinkedInstructionStream::Reader::read32()
109 {
110 const unsigned char* data = &m_stream.m_data.data()[m_index];
111 unsigned char type = data[0] >> 5;
112
113 switch (type) {
114 case Positive5Bit:
115 m_index++;
116 return data[0];
117 case Negative5Bit:
118 m_index++;
119 return 0xffffffe0 | data[0];
120 case Positive13Bit:
121 m_index += 2;
122 return ((data[0] & 0x1F) << 8) | data[1];
123 case Negative13Bit:
124 m_index += 2;
125 return 0xffffe000 | ((data[0] & 0x1F) << 8) | data[1];
126 case ConstantRegister5Bit:
127 m_index++;
128 return 0x40000000 | (data[0] & 0x1F);
129 case ConstantRegister13Bit:
130 m_index += 2;
131 return 0x40000000 | ((data[0] & 0x1F) << 8) | data[1];
132 default:
133 ASSERT(type == Full32Bit);
134 m_index += 5;
135 return data[1] | data[2] << 8 | data[3] << 16 | data[4] << 24;
136 }
137 }
138
139 ALWAYS_INLINE const UnlinkedInstruction* UnlinkedInstructionStream::Reader::next()
140 {
141 m_unpackedBuffer[0].u.opcode = static_cast<OpcodeID>(read8());
142 unsigned opLength = opcodeLength(m_unpackedBuffer[0].u.opcode);
143 for (unsigned i = 1; i < opLength; ++i)
144 m_unpackedBuffer[i].u.index = read32();
145 return m_unpackedBuffer;
146 }
147
148 } // namespace JSC
149
150 #endif // UnlinkedInstructionStream_h